# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License, Version 1.0 only # (the "License"). You may not use this file except in compliance # with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 1989,1997,1999 by Sun Microsystems, Inc. # All rights reserved. # # Copyright 2012 Milan Jurik. All rights reserved. # Copyright 2014 Nexenta Systems, Inc. All rights reserved. # # uts/common/gssd/Makefile # # include global definitions include ../../../Makefile.master INSTALLED_HDRS= gssapi.h gssapi_ext.h gssapi_krb5.h PRIVATE_HDRS= gssd.x gssd_prot.h HDRS= $(INSTALLED_HDRS) $(PRIVATE_HDRS) # Hammerhead: These are pre-generated and checked into the repo. # rpcgen + GNU cpp truncates %#define output from gssd.x. # If you need to regenerate, use illumos native rpcgen on OI. DERIVED_FILES= gssd_prot.h gssd_prot.c gssd_xdr.c GSSDDIRS= $(ROOT)/usr/include/gssapi GSSDHDRS= $(INSTALLED_HDRS:%=$(GSSDDIRS)/%) CHECKHDRS= $(INSTALLED_HDRS:%.h=%.check) # gssd_prot.h is rpcgen'ed and can never be made to pass # cstyle so it is unchecked UNCHECKED_HDRS= gss_prot.h # install rules $(GSSDDIRS)/%: % $(INS.file) $(GSSDDIRS)/%: mechs/krb5/include/% $(INS.file) # This is 3rd party code, so just skip hdrchk. gssapi_krb5.check: .KEEP_STATE: .PARALLEL: $(CHECKHDRS) install_h: all_h $(GSSDDIRS) $(GSSDHDRS) all_h: $(DERIVED_FILES) $(GSSDDIRS): $(INS.dir) # Hammerhead: Pre-generated files — do NOT regenerate with rpcgen. # Original rules preserved as comments for reference: # gssd_prot.h: $(RPCGEN) -CM -h gssd.x > $@ # gssd_prot.c: $(RPCGEN) -M -l gssd.x | sed ... > $@ # gssd_xdr.c: $(RPCGEN) -M -c gssd.x | sed ... > $@ check: $(CHECKHDRS) clean: @# Hammerhead: do NOT delete pre-generated DERIVED_FILES clobber: clean /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include /* * See krb5/gssapi_krb5.c for a description of the algorithm for * encoding an object identifier. */ /* * The OID of user_name is(gss_nt_user_name, GSS_C_NT_USER_NAME): * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * generic(1) user_name(1) = 1.2.840.113554.1.2.1.1 * machine_uid_name(gss_nt_machine_uid_name, GSS_C_NT_MACHINE_UID_NAME): * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * generic(1) machine_uid_name(2) = 1.2.840.113554.1.2.1.2 * string_uid_name(gss_nt_string_uid_name,GSS_C_NT_STRING_UID_NAME): * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * generic(1) string_uid_name(3) = 1.2.840.113554.1.2.1.3 * service_name(gss_nt_service_name): * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * generic(1) service_name(4) = 1.2.840.113554.1.2.1.4 * hostbased_service_name(GSS_C_NT_HOSTBASED_SERVICE) * iso(1) org(3) dod(6) 1(internet) 5(security) 6(nametypes) * 2(gss-host-based-services) == 1.3.6.1.5.6.2 * anonymous_name(GSS_C_NT_ANONYMOUS) * iso(1) org(3) dod(6) 1(internet) 5(security) 6(nametypes) * 3(anonymous) = 1.3.6.1.5.6.3 * export_name(GSS_C_NT_EXPORT) * iso(1) org(3) dod(6) 1(internet) 5(security) 6(nametypes) * 4(export) = 1.3.6.1.5.6.4 */ static const gss_OID_desc oids[] = { /* GSS_C_NT_USER_NAME */ {10, "\052\206\110\206\367\022\001\002\001\001"}, /* GSS_C_NT_MACHINE_UID_NAME */ {10, "\052\206\110\206\367\022\001\002\001\002"}, /* GSS_C_NT_STRING_UID_NAME */ {10, "\052\206\110\206\367\022\001\002\001\003"}, /* gss_nt_service_name */ {10, "\052\206\110\206\367\022\001\002\001\004"}, /* GSS_C_NT_HOSTBASED_SERVICE */ {6, "\053\006\001\005\006\002"}, /* GSS_C_NT_ANONYMOUS */ {6, "\053\006\001\005\006\003"}, /* GSS_C_NT_EXPORT_NAME */ {6, "\053\006\001\005\006\004"}, /* GSS_C_INQ_SSPI_SESSION_KEY */ {11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"}, }; const gss_OID_desc * const gss_nt_user_name = oids+0; const gss_OID_desc * const gss_nt_machine_uid_name = oids+1; const gss_OID_desc * const gss_nt_string_uid_name = oids+2; const gss_OID_desc * const gss_nt_service_name = oids+3; /* XXXXX These are needed for Kerberos */ const gss_OID_desc * const gss_nt_service_name_v2 = oids+4; const gss_OID_desc * const gss_nt_exported_name = oids+6; /* * These are added to reflect definitions in the * gss c-bindings spec. */ /* * The use of the following defines are preferred over the above defines. * This is because the following are the only ones defined * in GSS-API Specs. */ const gss_OID GSS_C_NT_USER_NAME = (gss_OID)oids+0; const gss_OID GSS_C_NT_MACHINE_UID_NAME = (gss_OID)oids+1; const gss_OID GSS_C_NT_STRING_UID_NAME = (gss_OID)oids+2; const gss_OID GSS_C_NT_HOSTBASED_SERVICE = (gss_OID)oids+4; const gss_OID GSS_C_NT_ANONYMOUS = (gss_OID)oids+5; const gss_OID GSS_C_NT_EXPORT_NAME = (gss_OID)oids+6; const gss_OID GSS_C_INQ_SSPI_SESSION_KEY = (gss_OID)oids+7; /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * glue routine for gss_display_name() */ #include #include OM_uint32 gss_display_name(OM_uint32 *minor_status, const gss_name_t input_name, gss_buffer_t output_name_buffer, gss_OID *output_name_type) { gss_union_name_t union_name; if (input_name == 0) return (GSS_S_BAD_NAME); union_name = (gss_union_name_t) input_name; GSSLOG(8, "union_name value %s\n", (char *)union_name->external_name->value); /* * copy the value of the external_name component of the union * name into the output_name_buffer and point the output_name_type * to the name_type component of union_name */ if (output_name_type != NULL) *output_name_type = union_name->name_type; if (output_name_buffer != NULL) { output_name_buffer->length = union_name->external_name->length; output_name_buffer->value = (void *) MALLOC(output_name_buffer->length); (void) memcpy(output_name_buffer->value, union_name->external_name->value, output_name_buffer->length); } if (minor_status) *minor_status = 0; return (GSS_S_COMPLETE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * glue routine gss_import_name * */ #include "mechglueP.h" #include OM_uint32 gss_import_name( OM_uint32 *minor_status, const gss_buffer_t input_name_buffer, const gss_OID input_name_type, gss_name_t *output_name) { gss_union_name_t union_name; OM_uint32 major_status = GSS_S_FAILURE; if (minor_status) *minor_status = 0; /* if output_name is NULL, simply return */ if (output_name == NULL) return (GSS_S_COMPLETE); *output_name = 0; if (input_name_buffer == GSS_C_NO_BUFFER || input_name_type == NULL) return (GSS_S_BAD_NAME); /* * First create the union name struct that will hold the external * name and the name type. */ union_name = (gss_union_name_t) MALLOC(sizeof (gss_union_name_desc)); if (!union_name) { *minor_status = ENOMEM; goto allocation_failure; } union_name->mech_type = 0; union_name->mech_name = 0; union_name->name_type = 0; union_name->external_name = 0; /* * All we do here is record the external name and name_type. * When the name is actually used, the underlying gss_import_name() * is called for the appropriate mechanism. * Since the name type may be a constant or comming from the * rpc resoults, we must make a copy. */ union_name->external_name = (gss_buffer_t) MALLOC(sizeof (gss_buffer_desc)); if (!union_name->external_name) { *minor_status = ENOMEM; goto allocation_failure; } union_name->external_name->length = input_name_buffer->length; union_name->external_name->value = (void *) MALLOC(input_name_buffer->length); if (!union_name->external_name->value) { *minor_status = ENOMEM; goto allocation_failure; } (void) memcpy(union_name->external_name->value, input_name_buffer->value, input_name_buffer->length); /* * making a copy of the name_type structure and elements * we now delete it when calling gss_release_name */ union_name->name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); if (!union_name->name_type) { *minor_status = ENOMEM; goto allocation_failure; } union_name->name_type->elements = (void *) MALLOC(input_name_type->length); if (!union_name->name_type->elements) { *minor_status = ENOMEM; goto allocation_failure; } (void) memcpy(union_name->name_type->elements, input_name_type->elements, input_name_type->length); union_name->name_type->length = input_name_type->length; *output_name = (gss_name_t) union_name; return (GSS_S_COMPLETE); allocation_failure: if (union_name) { if (union_name->external_name) { if (union_name->external_name->value) FREE(union_name->external_name->value, union_name->external_name->length); FREE(union_name->external_name, sizeof (gss_buffer_desc)); } if (union_name->name_type) { FREE(union_name->name_type, sizeof (gss_OID_desc)); } FREE(union_name, sizeof (gss_union_name_desc)); } return (major_status); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1996,1997, by Sun Microsystems, Inc. * All rights reserved. */ /* * glue routine for gss_release_buffer */ #include "mechglueP.h" OM_uint32 gss_release_buffer(OM_uint32 *minor_status, gss_buffer_t buffer) { if (minor_status) *minor_status = 0; /* if buffer is NULL, return */ if (buffer == GSS_C_NO_BUFFER) return (GSS_S_COMPLETE); if ((buffer->length) && (buffer->value)) { FREE(buffer->value, buffer->length); buffer->length = 0; buffer->value = NULL; } return (GSS_S_COMPLETE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1996,1997, by Sun Microsystems, Inc. * All rights reserved. */ /* * glue routine for gss_release_name */ #include "mechglueP.h" OM_uint32 gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) { gss_union_name_t union_name; /* if input_name is NULL, return error */ if (input_name == 0) return (GSS_S_BAD_NAME); /* * free up the space for the external_name, name_type * and then free the union_name descriptor */ union_name = (gss_union_name_t) *input_name; *input_name = 0; *minor_status = 0; if (union_name == NULL) return (GSS_S_BAD_NAME); FREE(union_name->external_name->value, union_name->external_name->length); FREE(union_name->external_name, sizeof (gss_buffer_desc)); /* free the name_type */ FREE(union_name->name_type->elements, union_name->name_type->length); FREE(union_name->name_type, sizeof (gss_OID_desc)); FREE(union_name, sizeof (gss_union_name_desc)); return (GSS_S_COMPLETE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1996,1997, by Sun Microsystems, Inc. * All rights reserved. */ /* * glue routine for gss_release_oid_set */ #include "mechglueP.h" OM_uint32 gss_release_oid_set(OM_uint32 *minor_status, gss_OID_set *set) { if (minor_status) *minor_status = 0; if (set == NULL) return (GSS_S_COMPLETE); if (*set == GSS_C_NULL_OID_SET) return (GSS_S_COMPLETE); FREE((*set)->elements, (*set)->count * sizeof (gss_OID_desc)); FREE(*set, sizeof (gss_OID_set_desc)); *set = GSS_C_NULL_OID_SET; return (GSS_S_COMPLETE); } /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GSSAPI_H_ #define _GSSAPI_H_ #ifdef __cplusplus extern "C" { #endif /* * First, include sys/types.h to get size_t defined. */ #include /* * If the platform supports the xom.h header file, it should be * included here. */ #ifdef HAVE_XOM_H #include #endif /* * Now define the three implementation-dependent types. */ struct gss_ctx_id; struct gss_cred_id; struct gss_name; typedef struct gss_ctx_id *gss_ctx_id_t; typedef struct gss_cred_id *gss_cred_id_t; typedef struct gss_name *gss_name_t; /* * The following type must be defined as the smallest natural * unsigned integer supported by the platform that has at least * 32 bits of precision. */ typedef unsigned int gss_uint32; typedef int gss_int32; #ifdef OM_STRING /* * We have included the xom.h header file. Verify that OM_uint32 * is defined correctly. */ #if sizeof (gss_uint32) != sizeof (OM_uint32) #error Incompatible definition of OM_uint32 from xom.h #endif typedef OM_object_identifier gss_OID_desc, *gss_OID; #else /* * We can't use X/Open definitions, so roll our own. */ typedef gss_uint32 OM_uint32; typedef struct gss_OID_desc_struct { OM_uint32 length; void*elements; } gss_OID_desc, *gss_OID; #endif typedef struct gss_OID_set_desc_struct { size_t count; gss_OID elements; } gss_OID_set_desc, *gss_OID_set; #ifdef _SYSCALL32 typedef struct gss_OID_desc_struct32 { OM_uint32 length; caddr32_t elements; } gss_OID_desc32, *gss_OID32; #endif /* _SYSCALL32 */ typedef struct gss_buffer_desc_struct { size_t length; void *value; } gss_buffer_desc, *gss_buffer_t; typedef struct gss_channel_bindings_struct { OM_uint32 initiator_addrtype; gss_buffer_desc initiator_address; OM_uint32 acceptor_addrtype; gss_buffer_desc acceptor_address; gss_buffer_desc application_data; } *gss_channel_bindings_t; /* * For now, define a QOP-type as an OM_uint32 */ typedef OM_uint32 gss_qop_t; typedef int gss_cred_usage_t; /* * Flag bits for context-level services. */ #define GSS_C_DELEG_FLAG 1 #define GSS_C_MUTUAL_FLAG 2 #define GSS_C_REPLAY_FLAG 4 #define GSS_C_SEQUENCE_FLAG 8 #define GSS_C_CONF_FLAG 16 #define GSS_C_INTEG_FLAG 32 #define GSS_C_ANON_FLAG 64 #define GSS_C_PROT_READY_FLAG 128 #define GSS_C_TRANS_FLAG 256 /* * Credential usage options */ #define GSS_C_BOTH 0 #define GSS_C_INITIATE 1 #define GSS_C_ACCEPT 2 /* * Status code types for gss_display_status */ #define GSS_C_GSS_CODE 1 #define GSS_C_MECH_CODE 2 /* * The constant definitions for channel-bindings address families */ #define GSS_C_AF_UNSPEC 0 #define GSS_C_AF_LOCAL 1 #define GSS_C_AF_INET 2 #define GSS_C_AF_IMPLINK 3 #define GSS_C_AF_PUP 4 #define GSS_C_AF_CHAOS 5 #define GSS_C_AF_NS 6 #define GSS_C_AF_NBS 7 #define GSS_C_AF_ECMA 8 #define GSS_C_AF_DATAKIT 9 #define GSS_C_AF_CCITT 10 #define GSS_C_AF_SNA 11 #define GSS_C_AF_DECnet 12 #define GSS_C_AF_DLI 13 #define GSS_C_AF_LAT 14 #define GSS_C_AF_HYLINK 15 #define GSS_C_AF_APPLETALK 16 #define GSS_C_AF_BSC 17 #define GSS_C_AF_DSS 18 #define GSS_C_AF_OSI 19 #define GSS_C_AF_X25 21 #define GSS_C_AF_NULLADDR 255 /* * Various Null values */ #define GSS_C_NO_NAME ((gss_name_t) 0) #define GSS_C_NO_BUFFER ((gss_buffer_t) 0) #define GSS_C_NO_OID ((gss_OID) 0) #define GSS_C_NO_OID_SET ((gss_OID_set) 0) #define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) #define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) #define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) #define GSS_C_EMPTY_BUFFER {0, NULL} /* * Some alternate names for a couple of the above * values. These are defined for V1 compatibility. */ #define GSS_C_NULL_OID GSS_C_NO_OID #define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET /* * Define the default Quality of Protection for per-message * services. Note that an implementation that offers multiple * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero * (as done here) to mean "default protection", or to a specific * explicit QOP value. However, a value of 0 should always be * interpreted by a GSSAPI implementation as a request for the * default protection level. */ #define GSS_C_QOP_DEFAULT 0 /* * Expiration time of 2^32-1 seconds means infinite lifetime for a * credential or security context */ #define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful) /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" * "\x01\x02\x01\x01"}, * corresponding to an object-identifier value of * {iso(1) member-body(2) United States(840) mit(113554) * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant * GSS_C_NT_USER_NAME should be initialized to point * to that gss_OID_desc. */ extern const gss_OID GSS_C_NT_USER_NAME; /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" * "\x01\x02\x01\x02"}, * corresponding to an object-identifier value of * {iso(1) member-body(2) United States(840) mit(113554) * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. * The constant GSS_C_NT_MACHINE_UID_NAME should be * initialized to point to that gss_OID_desc. */ extern const gss_OID GSS_C_NT_MACHINE_UID_NAME; /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" * "\x01\x02\x01\x03"}, * corresponding to an object-identifier value of * {iso(1) member-body(2) United States(840) mit(113554) * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. * The constant GSS_C_NT_STRING_UID_NAME should be * initialized to point to that gss_OID_desc. */ extern const 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 * {1(iso), 3(org), 6(dod), 1(internet), 5(security), * 6(nametypes), 2(gss-host-based-services)}. The constant * GSS_C_NT_HOSTBASED_SERVICE should be initialized to point * to that gss_OID_desc. */ extern const gss_OID GSS_C_NT_HOSTBASED_SERVICE; /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, * corresponding to an object identifier value of * {1(iso), 3(org), 6(dod), 1(internet), 5(security), * 6(nametypes), 3(gss-anonymous-name)}. The constant * and GSS_C_NT_ANONYMOUS should be initialized to point * to that gss_OID_desc. */ extern const gss_OID GSS_C_NT_ANONYMOUS; /* * The implementation must reserve static storage for a * gss_OID_desc object containing the value * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, * corresponding to an object-identifier value of * {1(iso), 3(org), 6(dod), 1(internet), 5(security), * 6(nametypes), 4(gss-api-exported-name)}. The constant * GSS_C_NT_EXPORT_NAME should be initialized to point * to that gss_OID_desc. */ extern const gss_OID GSS_C_NT_EXPORT_NAME; /* Major status codes */ #define GSS_S_COMPLETE 0 /* * Some "helper" definitions to make the status code macros obvious. */ #define GSS_C_CALLING_ERROR_OFFSET 24 #define GSS_C_ROUTINE_ERROR_OFFSET 16 #define GSS_C_SUPPLEMENTARY_OFFSET 0 #define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul) #define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul) #define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul) /* * The macros that test status codes for error conditions. * Note that the GSS_ERROR() macro has changed slightly from * the V1 GSSAPI so that it now evaluates its argument * only once. */ #define GSS_CALLING_ERROR(x) \ ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) #define GSS_ROUTINE_ERROR(x) \ ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) #define GSS_SUPPLEMENTARY_INFO(x) \ ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) #define GSS_ERROR(x) \ ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) /* * Now the actual status code definitions */ /* * Calling errors: */ #define GSS_S_CALL_INACCESSIBLE_READ \ (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET) #define GSS_S_CALL_INACCESSIBLE_WRITE \ (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET) #define GSS_S_CALL_BAD_STRUCTURE \ (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET) /* * Routine errors: */ #define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_MIC GSS_S_BAD_SIG #define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_DEFECTIVE_CREDENTIAL \ (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_CREDENTIALS_EXPIRED \ (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_CONTEXT_EXPIRED \ (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_DUPLICATE_ELEMENT \ (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET) #define GSS_S_NAME_NOT_MN (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET) /* * Supplementary info bits: */ #define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) #define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) #define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) #define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) #define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) /* * Finally, function prototypes for the GSS-API routines. */ OM_uint32 gss_acquire_cred( OM_uint32 *, /* minor_status */ const gss_name_t, /* desired_name */ OM_uint32, /* time_req */ const gss_OID_set, /* desired_mechs */ gss_cred_usage_t, /* cred_usage */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 * /* time_rec */ ); OM_uint32 gss_release_cred( OM_uint32 *, /* minor_status */ gss_cred_id_t * /* cred_handle */ ); OM_uint32 gss_init_sec_context( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* initiator_cred_handle */ gss_ctx_id_t *, /* context_handle */ const gss_name_t, /* target_name */ const gss_OID, /* mech_type */ OM_uint32, /* req_flags */ OM_uint32, /* time_req */ gss_channel_bindings_t, /* input_chan_bindings */ const gss_buffer_t, /* input_token */ gss_OID *, /* actual_mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 * /* time_rec */ ); OM_uint32 gss_accept_sec_context( OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ const gss_cred_id_t, /* acceptor_cred_handle */ const gss_buffer_t, /* input_token_buffer */ const gss_channel_bindings_t, /* input_chan_bindings */ gss_name_t *, /* src_name */ gss_OID *, /* mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 *, /* time_rec */ gss_cred_id_t * /* delegated_cred_handle */ ); OM_uint32 gss_process_context_token( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t /* token_buffer */ ); OM_uint32 gss_delete_sec_context( OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* output_token */ ); OM_uint32 gss_context_time( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ OM_uint32 * /* time_rec */ ); OM_uint32 gss_get_mic( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ gss_qop_t, /* qop_req */ const gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ ); OM_uint32 gss_verify_mic( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t, /* message_buffer */ const gss_buffer_t, /* token_buffer */ gss_qop_t * /* qop_state */ ); OM_uint32 gss_wrap( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ const gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t /* output_message_buffer */ ); OM_uint32 gss_unwrap( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ gss_qop_t * /* qop_state */ ); OM_uint32 gss_display_status( OM_uint32 *, /* minor_status */ OM_uint32, /* status_value */ int, /* status_type */ const gss_OID, /* mech_type */ OM_uint32 *, /* message_context */ gss_buffer_t /* status_string */ ); OM_uint32 gss_indicate_mechs( OM_uint32 *, /* minor_status */ gss_OID_set * /* mech_set */ ); OM_uint32 gss_compare_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* name1 */ const gss_name_t, /* name2 */ int * /* name_equal */ ); OM_uint32 gss_display_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_buffer_t, /* output_name_buffer */ gss_OID * /* output_name_type */ ); OM_uint32 gss_import_name( OM_uint32 *, /* minor_status */ const gss_buffer_t, /* input_name_buffer */ const gss_OID, /* input_name_type */ gss_name_t * /* output_name */ ); OM_uint32 gss_export_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_buffer_t /* exported_name */ ); OM_uint32 gss_release_name( OM_uint32 *, /* minor_status */ gss_name_t * /* input_name */ ); OM_uint32 gss_release_buffer( OM_uint32 *, /* minor_status */ gss_buffer_t /* buffer */ ); OM_uint32 gss_release_oid_set( OM_uint32 *, /* minor_status */ gss_OID_set * /* set */ ); OM_uint32 gss_inquire_cred( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* cred_handle */ gss_name_t *, /* name */ OM_uint32 *, /* lifetime */ gss_cred_usage_t *, /* cred_usage */ gss_OID_set * /* mechanisms */ ); OM_uint32 gss_inquire_context( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ gss_name_t *, /* src_name */ gss_name_t *, /* targ_name */ OM_uint32 *, /* lifetime_rec */ gss_OID *, /* mech_type */ OM_uint32 *, /* ctx_flags */ int *, /* locally_initiated */ int * /* open */ ); OM_uint32 gss_wrap_size_limit( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ OM_uint32, /* req_output_size */ OM_uint32 * /* max_input_size */ ); OM_uint32 gss_add_cred( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred_handle */ const gss_name_t, /* desired_name */ const gss_OID, /* desired_mech */ gss_cred_usage_t, /* cred_usage */ OM_uint32, /* initiator_time_req */ OM_uint32, /* acceptor_time_req */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 *, /* initiator_time_rec */ OM_uint32 * /* acceptor_time_rec */ ); OM_uint32 gss_store_cred( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred */ gss_cred_usage_t, /* cred_usage */ const gss_OID, /* desired_mech */ OM_uint32, /* overwrite_cred */ OM_uint32, /* default_cred */ gss_OID_set *, /* elements_stored */ gss_cred_usage_t * /* cred_usage_stored */ ); OM_uint32 gss_inquire_cred_by_mech( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* cred_handle */ const gss_OID, /* mech_type */ gss_name_t *, /* name */ OM_uint32 *, /* initiator_lifetime */ OM_uint32 *, /* acceptor_lifetime */ gss_cred_usage_t * /* cred_usage */ ); OM_uint32 gss_export_sec_context( OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* interprocess_token */ ); OM_uint32 gss_import_sec_context( OM_uint32 *, /* minor_status */ const gss_buffer_t, /* interprocess_token */ gss_ctx_id_t * /* context_handle */ ); OM_uint32 gss_create_empty_oid_set( OM_uint32 *, /* minor_status */ gss_OID_set * /* oid_set */ ); OM_uint32 gss_add_oid_set_member( OM_uint32 *, /* minor_status */ const gss_OID, /* member_oid */ gss_OID_set * /* oid_set */ ); OM_uint32 gss_test_oid_set_member( OM_uint32 *, /* minor_status */ const gss_OID, /* member */ const gss_OID_set, /* set */ int * /* present */ ); OM_uint32 gss_inquire_names_for_mech( OM_uint32 *, /* minor_status */ const gss_OID, /* mechanism */ gss_OID_set * /* name_types */ ); OM_uint32 gss_inquire_mechs_for_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_OID_set * /* mech_types */ ); OM_uint32 gss_canonicalize_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ const gss_OID, /* mech_type */ gss_name_t * /* output_name */ ); OM_uint32 gss_duplicate_name( OM_uint32 *, /* minor_status */ const gss_name_t, /* src_name */ gss_name_t * /* dest_name */ ); OM_uint32 gss_release_oid( OM_uint32 *, /* minor_status */ gss_OID * /* oid */ ); OM_uint32 gss_str_to_oid( OM_uint32 *, /* minor_status */ const gss_buffer_t, /* oid_str */ gss_OID * /* oid */ ); OM_uint32 gss_oid_to_str( OM_uint32 *, /* minor_status */ const gss_OID, /* oid */ gss_buffer_t /* oid_str */ ); /* * The following routines are obsolete variants of gss_get_mic, * gss_verify_mic, gss_wrap and gss_unwrap. They should be * provided by GSSAPI V2 implementations for backwards * compatibility with V1 applications. Distinct entrypoints * (as opposed to #defines) should be provided, both to allow * GSSAPI V1 applications to link against GSSAPI V2 implementations, * and to retain the slight parameter type differences between the * obsolete versions of these routines and their current forms. */ OM_uint32 gss_sign( OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ ); OM_uint32 gss_verify( OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* token_buffer */ int * /* qop_state */ ); OM_uint32 gss_seal( OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ int, /* qop_req */ gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t /* output_message_buffer */ ); OM_uint32 gss_unseal( OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ int * /* qop_state */ ); #ifdef _KERNEL /* For kernel */ #include void kgss_free_oid(gss_OID oid); OM_uint32 kgss_acquire_cred( OM_uint32 *, const gss_name_t, OM_uint32, const gss_OID_set, int, gss_cred_id_t *, gss_OID_set *, OM_uint32 *, uid_t); OM_uint32 kgss_add_cred( OM_uint32 *, gss_cred_id_t, gss_name_t, gss_OID, int, int, int, gss_OID_set *, OM_uint32 *, OM_uint32 *, uid_t); OM_uint32 kgss_release_cred( OM_uint32 *, gss_cred_id_t *, uid_t); OM_uint32 kgss_init_sec_context( OM_uint32 *, const gss_cred_id_t, gss_ctx_id_t *, const gss_name_t, const gss_OID, int, OM_uint32, const gss_channel_bindings_t, const gss_buffer_t, gss_OID *, gss_buffer_t, int *, OM_uint32 *, uid_t); OM_uint32 kgss_accept_sec_context( OM_uint32 *, gss_ctx_id_t *, const gss_cred_id_t, const gss_buffer_t, const gss_channel_bindings_t, const gss_buffer_t, gss_OID *, gss_buffer_t, int *, OM_uint32 *, gss_cred_id_t *, uid_t); OM_uint32 kgss_process_context_token( OM_uint32 *, const gss_ctx_id_t, const gss_buffer_t, uid_t); OM_uint32 kgss_delete_sec_context( OM_uint32 *, gss_ctx_id_t *, gss_buffer_t); OM_uint32 kgss_export_sec_context( OM_uint32 *, const gss_ctx_id_t, gss_buffer_t); OM_uint32 kgss_import_sec_context( OM_uint32 *, const gss_buffer_t, gss_ctx_id_t); OM_uint32 kgss_context_time( OM_uint32 *, const gss_ctx_id_t, OM_uint32 *, uid_t); OM_uint32 kgss_sign( OM_uint32 *, const gss_ctx_id_t, int, const gss_buffer_t, gss_buffer_t); OM_uint32 kgss_verify( OM_uint32 *, const gss_ctx_id_t, const gss_buffer_t, const gss_buffer_t, int *); OM_uint32 kgss_seal( OM_uint32 *, const gss_ctx_id_t, int, int, const gss_buffer_t, int *, gss_buffer_t); OM_uint32 kgss_unseal( OM_uint32 *, const gss_ctx_id_t, const gss_buffer_t, gss_buffer_t, int *, int *); OM_uint32 kgss_display_status( OM_uint32 *, OM_uint32, int, const gss_OID, int *, gss_buffer_t, uid_t); OM_uint32 kgss_indicate_mechs( OM_uint32 *, gss_OID_set *, uid_t); OM_uint32 kgss_inquire_cred( OM_uint32 *, const gss_cred_id_t, gss_name_t *, OM_uint32 *, int *, gss_OID_set *, uid_t); OM_uint32 kgss_inquire_cred_by_mech( OM_uint32 *, gss_cred_id_t, gss_OID, uid_t); #endif /* if _KERNEL */ #ifdef __cplusplus } #endif #endif /* _GSSAPI_H_ */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Private extensions and utilities to the GSS-API. * These are not part of the GSS-API specification * but may be useful to GSS-API users. */ #ifndef _GSSAPI_EXT_H #define _GSSAPI_EXT_H #include #ifdef _KERNEL #include #else #include #endif #ifdef __cplusplus extern "C" { #endif /* MACRO for comparison of gss_OID's */ #define g_OID_equal(o1, o2) \ (((o1)->length == (o2)->length) && \ (memcmp((o1)->elements, (o2)->elements, (int)(o1)->length) == 0)) /* * MACRO for copying of OIDs - memory must already be allocated * o2 is copied to o1 */ #define g_OID_copy(o1, o2) \ bcopy((o2)->elements, (o1)->elements, (o2)->length);\ (o1)->length = (o2)->length; /* MACRO to check if input buffer is valid */ #define GSS_EMPTY_BUFFER(buf) ((buf) == NULL ||\ (buf)->value == NULL || (buf)->length == 0) /* * GSSAPI Extension functions -- these functions aren't * in the GSSAPI specification, but are provided in our * GSS library. */ #ifndef _KERNEL /* * qop configuration file handling. */ #define MAX_QOP_NUM_PAIRS 128 #define MAX_QOPS_PER_MECH 128 typedef struct _qop_num { char *qop; OM_uint32 num; char *mech; } qop_num; OM_uint32 __gss_qop_to_num( char *qop, /* input qop string */ char *mech, /* input mech string */ OM_uint32 *num /* output qop num */ ); OM_uint32 __gss_num_to_qop( char *mech, /* input mech string */ OM_uint32 num, /* input qop num */ char **qop /* output qop name */ ); OM_uint32 __gss_get_mech_info( char *mech, /* input mech string */ char **qops /* buffer for return qops */ ); OM_uint32 __gss_mech_qops( char *mech, /* input mech */ qop_num *mech_qops, /* mech qops buffer */ int *numqops /* buffer to return numqops */ ); OM_uint32 __gss_mech_to_oid( const char *mech, /* mechanism string name */ gss_OID *oid /* mechanism oid */ ); const char * __gss_oid_to_mech( const gss_OID oid /* mechanism oid */ ); OM_uint32 __gss_get_mechanisms( char *mechArray[], /* array to populate with mechs */ int arrayLen /* length of passed in array */ ); OM_uint32 __gss_get_mech_type( gss_OID oid, /* mechanism oid */ const gss_buffer_t token /* token */ ); OM_uint32 __gss_userok( OM_uint32 *, /* minor status */ const gss_name_t, /* remote user principal name */ const char *, /* local unix user name */ int *); /* remote principal ok to login w/out pw? */ OM_uint32 gsscred_expname_to_unix_cred( const gss_buffer_t, /* export name */ uid_t *, /* uid out */ gid_t *, /* gid out */ gid_t *[], /* gid array out */ int *); /* gid array length */ OM_uint32 gsscred_name_to_unix_cred( const gss_name_t, /* gss name */ const gss_OID, /* mechanim type */ uid_t *, /* uid out */ gid_t *, /* gid out */ gid_t *[], /* gid array out */ int *); /* gid array length */ /* * The following function will be used to resolve group * ids from a UNIX uid. */ OM_uint32 gss_get_group_info( const uid_t, /* entity UNIX uid */ gid_t *, /* gid out */ gid_t *[], /* gid array */ int *); /* length of the gid array */ OM_uint32 gss_acquire_cred_with_password( OM_uint32 * minor_status, const gss_name_t desired_name, const gss_buffer_t password, OM_uint32 time_req, const gss_OID_set desired_mechs, int cred_usage, gss_cred_id_t *output_cred_handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec); OM_uint32 gss_add_cred_with_password( OM_uint32 *minor_status, const gss_cred_id_t input_cred_handle, const gss_name_t desired_name, const gss_OID desired_mech, const gss_buffer_t password, gss_cred_usage_t cred_usage, OM_uint32 initiator_time_req, OM_uint32 acceptor_time_req, gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *initiator_time_rec, OM_uint32 *acceptor_time_rec); /* * Returns a buffer set with the first member containing the * session key for SSPI compatibility. The optional second * member contains an OID identifying the session key type. */ extern const gss_OID GSS_C_INQ_SSPI_SESSION_KEY; /* * For compatability with other GSSAPI implementations. * This is needed by Samba. */ extern const gss_OID_desc * const gss_mech_krb5; #else /* _KERNEL */ OM_uint32 kgsscred_expname_to_unix_cred( const gss_buffer_t expName, uid_t *uidOut, gid_t *gidOut, gid_t *gids[], int *gidsLen, uid_t uid); OM_uint32 kgsscred_name_to_unix_cred( const gss_name_t intName, const gss_OID mechType, uid_t *uidOut, gid_t *gidOut, gid_t *gids[], int *gidsLen, uid_t uid); OM_uint32 kgss_get_group_info( const uid_t puid, gid_t *gidOut, gid_t *gids[], int *gidsLen, uid_t uid); #endif /* * GGF extensions */ typedef struct gss_buffer_set_desc_struct { size_t count; gss_buffer_desc *elements; } gss_buffer_set_desc, *gss_buffer_set_t; #define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t)0) OM_uint32 gss_create_empty_buffer_set (OM_uint32 *, /* minor_status */ gss_buffer_set_t *); /* buffer_set */ OM_uint32 gss_add_buffer_set_member (OM_uint32 *, /* minor_status */ const gss_buffer_t, /* member_buffer */ gss_buffer_set_t *); /* buffer_set */ OM_uint32 gss_release_buffer_set (OM_uint32 *, /* minor_status */ gss_buffer_set_t *); /* buffer_set */ OM_uint32 gss_inquire_sec_context_by_oid (OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_OID, /* desired_object */ gss_buffer_set_t *); /* data_set */ #ifdef __cplusplus } #endif #endif /* _GSSAPI_EXT_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ %/* % * Copyright 2004 Sun Microsystems, Inc. All rights reserved. % * Use is subject to license terms. % */ % %/* % * RPC protocol information for gssd, the usermode daemon that % * assists the kernel with gssapi. It is gssd that executes all % * gssapi calls except for some such as gss_sign(), and % * gss_verify(), which are executed in the kernel itself. % * % * File generated from gssd.x % */ % %#define NO 0 %#define YES 1 %#define FOREVER 1 % %#include %#include %#include %#ifndef _KERNEL %#include %#endif /* not _KERNEL */ % %#ifdef _KERNEL %extern void killgssd_handle(CLIENT *); %extern CLIENT *getgssd_handle(void); %#endif /* _KERNEL */ % /* * These are the definitions for the interface to GSSD. */ typedef unsigned int OM_UINT32; typedef opaque GSS_CTX_ID_T<>; typedef opaque GSS_CRED_ID_T<>; typedef opaque GSS_OID<>; typedef opaque GSS_BUFFER_T<>; typedef gid_t GSSCRED_GIDS<>; typedef GSS_OID GSS_OID_SET<>; struct GSS_CHANNEL_BINDINGS_STRUCT { int present; OM_UINT32 initiator_addrtype; GSS_BUFFER_T initiator_address; OM_UINT32 acceptor_addrtype; GSS_BUFFER_T acceptor_address; GSS_BUFFER_T application_data; }; typedef struct GSS_CHANNEL_BINDINGS_STRUCT GSS_CHANNEL_BINDINGS; struct gss_acquire_cred_arg { uid_t uid; /* client uid */ GSS_BUFFER_T desired_name; /* name of cred */ GSS_OID name_type; /* type of desired name */ OM_UINT32 time_req; /* context validity interval */ GSS_OID_SET desired_mechs; /* cred mechanisms */ int cred_usage; /* init/accept/both */ }; struct gss_acquire_cred_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_CRED_ID_T output_cred_handle; /* returned credential handle */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_OID_SET actual_mechs; /* found cred mechanisms */ OM_UINT32 time_rec; /* actual context validity */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_add_cred_arg { uid_t uid; /* client uid */ GSS_CRED_ID_T input_cred_handle; /* input credential handle */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_BUFFER_T desired_name; /* name of cred */ GSS_OID name_type; /* type of desired name */ GSS_OID desired_mech_type; /* cred mechanisms */ int cred_usage; /* init/accept/both */ OM_UINT32 initiator_time_req; /* context validity interval */ OM_UINT32 acceptor_time_req; /* context validity interval */ }; /* Note: For gss_add_cred we always update the underlying credentials of * input_cred_handle. We always pass NULL as output_cred_handle when the call * to gss_add_cred is made */ struct gss_add_cred_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_OID_SET actual_mechs; /* found cred mechanisms */ OM_UINT32 initiator_time_rec; /* cred validity interval */ OM_UINT32 acceptor_time_rec; /* cred validity interval */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_release_cred_arg { uid_t uid; /* client uid */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handles */ GSS_CRED_ID_T cred_handle; /* credential handle */ }; struct gss_release_cred_res { OM_UINT32 minor_status; /* status from the mechanism */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_init_sec_context_arg { uid_t uid; /* client uid */ GSS_CTX_ID_T context_handle; /* handle to existing context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CRED_ID_T claimant_cred_handle; /* must = GSS_C_NO_CREDENTIAL */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_BUFFER_T target_name; /* name of server */ GSS_OID name_type; /* type of principal name */ GSS_OID mech_type; /* requested mechanism */ int req_flags; /* requested context options */ OM_UINT32 time_req; /* context validity interval */ GSS_CHANNEL_BINDINGS input_chan_bindings; /* requested channel bindings */ GSS_BUFFER_T input_token; /* token to send to peer */ }; struct gss_init_sec_context_res { GSS_CTX_ID_T context_handle; /* handle to created context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ OM_UINT32 minor_status; /* status from the mechanism */ GSS_OID actual_mech_type; /* actual mechanism used */ GSS_BUFFER_T output_token; /* where peer token is put */ OM_UINT32 ret_flags; /* options of context */ OM_UINT32 time_rec; /* actual context validity */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_accept_sec_context_arg { uid_t uid; /* client uid */ GSS_CTX_ID_T context_handle; /* handle to existing context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CRED_ID_T verifier_cred_handle; /* must = GSS_C_NO_CREDENTIAL */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_BUFFER_T input_token_buffer; /* token to send to peer */ GSS_CHANNEL_BINDINGS input_chan_bindings; /* requested channel bindings */ }; struct gss_accept_sec_context_res { GSS_CTX_ID_T context_handle; /* handle to created context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ OM_UINT32 minor_status; /* status from the mechanism */ GSS_BUFFER_T src_name; /* authenticated name of peer */ GSS_OID mech_type; /* mechanism used */ GSS_BUFFER_T output_token; /* where peer token is put */ OM_UINT32 ret_flags; /* options of context */ OM_UINT32 time_rec; /* actual context validity */ GSS_CRED_ID_T delegated_cred_handle; /* always GSS_C_NO_CREDENTIAL */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_process_context_token_arg { uid_t uid; /* client uid */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ GSS_BUFFER_T token_buffer; /* token to process */ }; struct gss_process_context_token_res { OM_UINT32 minor_status; /* status from the mechanism */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_delete_sec_context_arg { OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ }; struct gss_delete_sec_context_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_CTX_ID_T context_handle; /* handle to deleted context */ GSS_BUFFER_T output_token; /* output token for peer */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_export_sec_context_arg { GSS_CTX_ID_T context_handle; /* handle to existing context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ }; struct gss_export_sec_context_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_CTX_ID_T context_handle; /* handle to existing context */ GSS_BUFFER_T output_token; /* input token for import_sec_context */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_import_sec_context_arg { GSS_BUFFER_T input_token; /* input token for import_sec_context */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ }; struct gss_import_sec_context_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_CTX_ID_T context_handle; /* handle to created context */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_context_time_arg { uid_t uid; /* client uid */ OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ }; struct gss_context_time_res { OM_UINT32 minor_status; /* status from the mechanism */ OM_UINT32 time_rec; /* actual context validity */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_sign_arg { OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ int qop_req; /* quality of protection */ GSS_BUFFER_T message_buffer; /* message to sign */ }; struct gss_sign_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_BUFFER_T msg_token; /* msg_token */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_verify_arg { OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ GSS_BUFFER_T message_buffer; /* message to verify */ GSS_BUFFER_T token_buffer; /* buffer containg token */ }; struct gss_verify_res { OM_UINT32 minor_status; /* status from the mechanism */ int qop_state; /* quality of protection */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_seal_arg { OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ int conf_req_flag; /* type of conf requested */ int qop_req; /* quality of prot. requested */ GSS_BUFFER_T input_message_buffer; /* message to protect */ }; struct gss_seal_res { OM_UINT32 minor_status; /* status from the mechanism */ int conf_state; /* type of conf. applied */ GSS_BUFFER_T output_message_buffer; /* protected message */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_unseal_arg { OM_UINT32 gssd_context_verifier; /* verifier for context handles */ GSS_CTX_ID_T context_handle; /* handle to existing context */ GSS_BUFFER_T input_message_buffer; /* message to protect */ }; struct gss_unseal_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_BUFFER_T output_message_buffer; /* protected message */ int conf_state; /* type of conf. provided */ int qop_state; /* quality of prot. provided */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_display_status_arg { uid_t uid; /* client uid */ int status_value; /* status to be converted */ int status_type; /* GSS or mech status */ GSS_OID mech_type; /* mechanism */ OM_UINT32 message_context; /* recursion flag */ }; struct gss_display_status_res { OM_UINT32 minor_status; /* status from the mechanism */ int message_context; /* recursion flag */ GSS_BUFFER_T status_string; /* text equiv of status */ OM_UINT32 status; /* status of GSSAPI call */ }; %/* gss_indicate_mechs_arg is void. This appears in the rpc call def */ struct gss_indicate_mechs_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_OID_SET mech_set; /* mechanism set supported */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_inquire_cred_arg { uid_t uid; /* client uid */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_CRED_ID_T cred_handle; /* credential handle */ }; struct gss_inquire_cred_res { OM_UINT32 minor_status; /* status from the mechanism */ GSS_BUFFER_T name; /* name associated with cred */ GSS_OID name_type; /* type of name */ OM_UINT32 lifetime; /* remaining validiy period */ int cred_usage; /* how creds may be used */ GSS_OID_SET mechanisms; /* mechs associated with cred */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gss_inquire_cred_by_mech_arg { uid_t uid; /* client uid */ OM_UINT32 gssd_cred_verifier; /* verifier for cred handle */ GSS_CRED_ID_T cred_handle; /* credential handle */ GSS_OID mech_type; /* cred mechanism */ }; struct gss_inquire_cred_by_mech_res { OM_UINT32 minor_status; /* status from the mechanism */ OM_UINT32 status; /* status of GSSAPI call */ }; struct gsscred_name_to_unix_cred_arg { uid_t uid; /* client uid */ GSS_BUFFER_T pname; /* principal name */ GSS_OID name_type; /* oid of principal name */ GSS_OID mech_type; /* for which mechanism to use */ }; struct gsscred_name_to_unix_cred_res { uid_t uid; /* principal's uid */ gid_t gid; /* principal's gid */ GSSCRED_GIDS gids; /* array of principal's gids */ OM_UINT32 major; /* status of the GSSAPI call */ }; struct gsscred_expname_to_unix_cred_arg { uid_t uid; /* client uid */ GSS_BUFFER_T expname; /* principal in export format */ }; struct gsscred_expname_to_unix_cred_res { uid_t uid; /* principal's uid */ gid_t gid; /* principal's gid */ GSSCRED_GIDS gids; /* array of principal's gids */ OM_UINT32 major; /* major status code */ }; struct gss_get_group_info_arg { uid_t uid; /* client uid */ uid_t puid; /* principal's uid */ }; struct gss_get_group_info_res { gid_t gid; /* principal's gid */ GSSCRED_GIDS gids; /* array of principal's gids */ OM_UINT32 major; /* major status code */ }; struct gss_get_kmod_arg { GSS_OID mech_oid; }; union gss_get_kmod_res switch (bool module_follow) { case TRUE: string modname<>; case FALSE: void; }; /* * The server accepts requests only from the loopback address. * Unix authentication is used, and the port must be in the reserved range. */ program GSSPROG { version GSSVERS { /* * Called by the client to acquire a credential. */ gss_acquire_cred_res GSS_ACQUIRE_CRED(gss_acquire_cred_arg) = 1; /* * Called by the client to release a credential. */ gss_release_cred_res GSS_RELEASE_CRED(gss_release_cred_arg) = 2; /* * Called by the client to initialize a security context. */ gss_init_sec_context_res GSS_INIT_SEC_CONTEXT(gss_init_sec_context_arg) = 3; /* * Called by the server to initialize a security context. */ gss_accept_sec_context_res GSS_ACCEPT_SEC_CONTEXT(gss_accept_sec_context_arg) = 4; /* * Called to pass token to underlying mechanism. */ gss_process_context_token_res GSS_PROCESS_CONTEXT_TOKEN(gss_process_context_token_arg) = 5; /* * Called to delete a security context. */ gss_delete_sec_context_res GSS_DELETE_SEC_CONTEXT(gss_delete_sec_context_arg) = 6; /* * Called to get remaining time security context has to live. */ gss_context_time_res GSS_CONTEXT_TIME(gss_context_time_arg) = 7; /* * Called to sign a message. */ gss_sign_res GSS_SIGN(gss_sign_arg) = 8; /* * Called to verify a signed message. */ gss_verify_res GSS_VERIFY(gss_verify_arg) = 9; /* * Called to translate minor status into a string. */ gss_display_status_res GSS_DISPLAY_STATUS(gss_display_status_arg) = 10; /* * Called to indicate which underlying mechanisms are supported */ gss_indicate_mechs_res GSS_INDICATE_MECHS(void) = 11; /* * Called by the client to inquire about a credential. */ gss_inquire_cred_res GSS_INQUIRE_CRED(gss_inquire_cred_arg) = 12; /* * Called to seal a message. */ gss_seal_res GSS_SEAL(gss_seal_arg) = 13; /* * Called to unseal a message. */ gss_unseal_res GSS_UNSEAL(gss_unseal_arg) = 14; /* * gsscred interface functions to obtain principal uid and gids */ gsscred_expname_to_unix_cred_res GSSCRED_EXPNAME_TO_UNIX_CRED( gsscred_expname_to_unix_cred_arg) = 15; gsscred_name_to_unix_cred_res GSSCRED_NAME_TO_UNIX_CRED( gsscred_name_to_unix_cred_arg) = 16; gss_get_group_info_res GSS_GET_GROUP_INFO(gss_get_group_info_arg) = 17; gss_get_kmod_res GSS_GET_KMOD(gss_get_kmod_arg) = 18; gss_export_sec_context_res GSS_EXPORT_SEC_CONTEXT(gss_export_sec_context_arg) = 19; gss_import_sec_context_res GSS_IMPORT_SEC_CONTEXT(gss_import_sec_context_arg) = 20; /* * Called by the client to add to a credential. */ gss_add_cred_res GSS_ADD_CRED(gss_add_cred_arg) = 21; gss_inquire_cred_by_mech_res GSS_INQUIRE_CRED_BY_MECH(gss_inquire_cred_by_mech_arg) = 22; } = 1; } = 100234; /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. */ /* * GSSAPI library stub module for gssd. */ #include #include "gssd_prot.h" #include #include #include #include #include #include #include #ifdef GSSDEBUG /* * Kernel kgssd module debugging aid. The global variable "gss_log" * is a bit mask which allows various types of debugging messages * to be printed out. * * gss_log & 1 will cause actual failures to be printed. * gss_log & 2 will cause informational messages to be * printed on the client side of kgssd. * gss_log & 4 will cause informational messages to be * printed on the server side of kgssd. * gss_log & 8 will cause informational messages to be * printed on both client and server side of kgssd. */ uint_t gss_log = 1; #endif /* GSSDEBUG */ #ifdef DEBUG extern void prom_printf(const char *, ...); #endif char *server = "localhost"; static OM_uint32 kgss_sign_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int, gss_buffer_t, gss_buffer_t, OM_uint32); static OM_uint32 kgss_verify_wrapped(void *, OM_uint32 *, gss_ctx_id_t, gss_buffer_t, gss_buffer_t, int *qop_state, OM_uint32); static OM_uint32 kgss_seal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, int, int, gss_buffer_t, int *, gss_buffer_t, OM_uint32); static OM_uint32 kgss_unseal_wrapped(void *, OM_uint32 *, gss_ctx_id_t, gss_buffer_t, gss_buffer_t, int *conf_state, int *qop_state, OM_uint32); static OM_uint32 kgss_delete_sec_context_wrapped(void *, OM_uint32 *, gssd_ctx_id_t *, gss_buffer_t, OM_uint32); static void __kgss_reset_mech(gss_mechanism *, gss_OID); #define DEFAULT_MINOR_STAT ((OM_uint32) ~0) OM_uint32 kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec, uid, gssd_cred_verifier) OM_uint32 *minor_status; const gss_name_t desired_name; OM_uint32 time_req; const gss_OID_set desired_mechs; int cred_usage; gssd_cred_id_t *output_cred_handle; gss_OID_set *actual_mechs; OM_uint32 *time_rec; uid_t uid; OM_uint32 *gssd_cred_verifier; { CLIENT *clnt; OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; enum clnt_stat client_stat; int i; gss_acquire_cred_arg arg; gss_acquire_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_acquire_cred: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* convert the desired name from internal to external format */ if (gss_display_name(&minor_status_temp, desired_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; killgssd_handle(clnt); GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.time_req = time_req; if (desired_mechs != GSS_C_NULL_OID_SET) { arg.desired_mechs.GSS_OID_SET_len = (uint_t)desired_mechs->count; arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *) MALLOC(sizeof (GSS_OID) * desired_mechs->count); for (i = 0; i < desired_mechs->count; i++) { arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len = (uint_t)desired_mechs->elements[i].length; arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val = (char *)MALLOC(desired_mechs->elements[i].length); (void) memcpy( arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, desired_mechs->elements[i].elements, desired_mechs->elements[i].length); } } else arg.desired_mechs.GSS_OID_SET_len = 0; arg.cred_usage = cred_usage; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); client_stat = gss_acquire_cred_1(&arg, &res, clnt); (void) gss_release_buffer(&minor_status_temp, &external_name); if (desired_mechs != GSS_C_NULL_OID_SET) { for (i = 0; i < desired_mechs->count; i++) FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len); FREE(arg.desired_mechs.GSS_OID_SET_val, arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID)); } if (client_stat != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return * GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (output_cred_handle != NULL) *output_cred_handle = 0; if (actual_mechs != NULL) *actual_mechs = NULL; if (time_rec != NULL) *time_rec = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_acquire_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_cred_handle != NULL && (res.status == GSS_S_COMPLETE)) { *output_cred_handle = *((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val); *gssd_cred_verifier = res.gssd_cred_verifier; } if (res.status == GSS_S_COMPLETE && res.actual_mechs.GSS_OID_SET_len != 0 && actual_mechs != NULL) { *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*actual_mechs)->count = (int)res.actual_mechs.GSS_OID_SET_len; (*actual_mechs)->elements = (gss_OID) MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); for (i = 0; i < (*actual_mechs)->count; i++) { (*actual_mechs)->elements[i].length = (OM_uint32) res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; (*actual_mechs)->elements[i].elements = (void *) MALLOC((*actual_mechs)->elements[i].length); (void) memcpy((*actual_mechs)->elements[i].elements, res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, (*actual_mechs)->elements[i].length); } } else { if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) (*actual_mechs) = NULL; } if (time_rec != NULL) *time_rec = res.time_rec; /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_acquire_cred(minor_status, desired_name, time_req, desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec, uid) OM_uint32 *minor_status; const gss_name_t desired_name; OM_uint32 time_req; const gss_OID_set desired_mechs; int cred_usage; gss_cred_id_t *output_cred_handle; gss_OID_set *actual_mechs; OM_uint32 *time_rec; uid_t uid; { OM_uint32 err; struct kgss_cred *kcred; kcred = KGSS_CRED_ALLOC(); *output_cred_handle = (gss_cred_id_t)kcred; err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs, time_rec, uid, &kcred->gssd_cred_verifier); if (GSS_ERROR(err)) { KGSS_CRED_FREE(kcred); *output_cred_handle = GSS_C_NO_CREDENTIAL; } return (err); } OM_uint32 kgss_add_cred_wrapped(minor_status, input_cred_handle, gssd_cred_verifier, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid) OM_uint32 *minor_status; gssd_cred_id_t input_cred_handle; OM_uint32 gssd_cred_verifier; gss_name_t desired_name; gss_OID desired_mech_type; int cred_usage; int initiator_time_req; int acceptor_time_req; gss_OID_set *actual_mechs; OM_uint32 *initiator_time_rec; OM_uint32 *acceptor_time_rec; uid_t uid; { CLIENT *clnt; OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; int i; gss_add_cred_arg arg; gss_add_cred_res res; /* * NULL the params here once * If there are errors then we won't * have to do it for every error * case */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (actual_mechs != NULL) *actual_mechs = NULL; if (initiator_time_rec != NULL) *initiator_time_rec = 0; if (acceptor_time_rec != NULL) *acceptor_time_rec = 0; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_add_cred: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* convert the desired name from internal to external format */ if (gss_display_name(&minor_status_temp, desired_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; killgssd_handle(clnt); GSSLOG0(1, "kgss_acquire_cred: display name failed\n"); return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32)uid; arg.input_cred_handle.GSS_CRED_ID_T_len = input_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.desired_mech_type.GSS_OID_len = (uint_t)(desired_mech_type != GSS_C_NULL_OID ? desired_mech_type->length : 0); arg.desired_mech_type.GSS_OID_val = (char *)(desired_mech_type != GSS_C_NULL_OID ? desired_mech_type->elements : 0); arg.cred_usage = cred_usage; arg.initiator_time_req = initiator_time_req; arg.acceptor_time_req = acceptor_time_req; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return * GSS_S_FAILURE */ killgssd_handle(clnt); (void) gss_release_buffer(&minor_status_temp, &external_name); GSSLOG0(1, "kgss_add_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* free the allocated memory for the flattened name */ (void) gss_release_buffer(&minor_status_temp, &external_name); /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.status == GSS_S_COMPLETE && res.actual_mechs.GSS_OID_SET_len != 0 && actual_mechs != NULL) { *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*actual_mechs)->count = (int)res.actual_mechs.GSS_OID_SET_len; (*actual_mechs)->elements = (gss_OID) MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); for (i = 0; i < (*actual_mechs)->count; i++) { (*actual_mechs)->elements[i].length = (OM_uint32) res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; (*actual_mechs)->elements[i].elements = (void *) MALLOC((*actual_mechs)->elements[i].length); (void) memcpy((*actual_mechs)->elements[i].elements, res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, (*actual_mechs)->elements[i].length); } } else { if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) (*actual_mechs) = NULL; } if (initiator_time_rec != NULL) *initiator_time_rec = res.acceptor_time_rec; if (acceptor_time_rec != NULL) *acceptor_time_rec = res.acceptor_time_rec; /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid) OM_uint32 *minor_status; gss_cred_id_t input_cred_handle; gss_name_t desired_name; gss_OID desired_mech_type; int cred_usage; int initiator_time_req; int acceptor_time_req; gss_OID_set *actual_mechs; OM_uint32 *initiator_time_rec; OM_uint32 *acceptor_time_rec; uid_t uid; { OM_uint32 err; OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_input_cred_handle; if (input_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle); gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle); } else { gssd_input_cred_handle = GSSD_NO_CREDENTIAL; } err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle, gssd_cred_verifier, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid); return (err); } OM_uint32 kgss_release_cred_wrapped(minor_status, cred_handle, uid, gssd_cred_verifier) OM_uint32 *minor_status; gssd_cred_id_t *cred_handle; uid_t uid; OM_uint32 gssd_cred_verifier; { CLIENT *clnt; gss_release_cred_arg arg; gss_release_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_release_cred: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32)uid; arg.gssd_cred_verifier = gssd_cred_verifier; if (cred_handle != NULL) { arg.cred_handle.GSS_CRED_ID_T_len = (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle; } else arg.cred_handle.GSS_CRED_ID_T_len = 0; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (cred_handle != NULL) *cred_handle = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_release_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* if the release succeeded, null out the cred_handle */ if (res.status == GSS_S_COMPLETE && cred_handle != NULL) *cred_handle = 0; /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* return with status returned in rpc call */ killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_release_cred(minor_status, cred_handle, uid) OM_uint32 *minor_status; gss_cred_id_t *cred_handle; uid_t uid; { OM_uint32 err; struct kgss_cred *kcred; if (*cred_handle == GSS_C_NO_CREDENTIAL) return (GSS_S_COMPLETE); else kcred = KCRED_TO_KGSS_CRED(*cred_handle); err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred, uid, kcred->gssd_cred_verifier); KGSS_CRED_FREE(kcred); *cred_handle = GSS_C_NO_CREDENTIAL; return (err); } static OM_uint32 kgss_init_sec_context_wrapped( OM_uint32 *minor_status, const gssd_cred_id_t claimant_cred_handle, OM_uint32 gssd_cred_verifier, gssd_ctx_id_t *context_handle, OM_uint32 *gssd_context_verifier, const gss_name_t target_name, const gss_OID mech_type, int req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token, gss_OID *actual_mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, uid_t uid) { CLIENT *clnt; OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; gss_init_sec_context_arg arg; gss_init_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_init_sec_context: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* convert the target name from internal to external format */ if (gss_display_name(&minor_status_temp, target_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; killgssd_handle(clnt); GSSLOG0(1, "kgss_init_sec_context: can't display name\n"); return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32)uid; arg.context_handle.GSS_CTX_ID_T_len = *context_handle == GSSD_NO_CONTEXT ? 0 : (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = *gssd_context_verifier; arg.claimant_cred_handle.GSS_CRED_ID_T_len = claimant_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.claimant_cred_handle.GSS_CRED_ID_T_val = (char *)&claimant_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); arg.req_flags = req_flags; arg.time_req = time_req; if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { arg.input_chan_bindings.present = YES; arg.input_chan_bindings.initiator_addrtype = input_chan_bindings->initiator_addrtype; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->initiator_address.length; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = (void *)input_chan_bindings->initiator_address.value; arg.input_chan_bindings.acceptor_addrtype = input_chan_bindings->acceptor_addrtype; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->acceptor_address.length; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = (void *)input_chan_bindings->acceptor_address.value; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->application_data.length; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = (void *)input_chan_bindings->application_data.value; } else { arg.input_chan_bindings.present = NO; arg.input_chan_bindings.initiator_addrtype = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.acceptor_addrtype = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; } arg.input_token.GSS_BUFFER_T_len = (uint_t)(input_token != GSS_C_NO_BUFFER ? input_token->length : 0); arg.input_token.GSS_BUFFER_T_val = (char *)(input_token != GSS_C_NO_BUFFER ? input_token->value : 0); /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (actual_mech_type != NULL) *actual_mech_type = NULL; if (output_token != NULL) output_token->length = 0; if (ret_flags != NULL) *ret_flags = 0; if (time_rec != NULL) *time_rec = 0; killgssd_handle(clnt); (void) gss_release_buffer(&minor_status_temp, &external_name); GSSLOG0(1, "kgss_init_sec_context: RPC call times out\n"); return (GSS_S_FAILURE); } /* free the allocated memory for the flattened name */ (void) gss_release_buffer(&minor_status_temp, &external_name); if (minor_status != NULL) *minor_status = res.minor_status; if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = (size_t)res.output_token.GSS_BUFFER_T_len; output_token->value = (void *)MALLOC(output_token->length); (void) memcpy(output_token->value, res.output_token.GSS_BUFFER_T_val, output_token->length); } /* if the call was successful, copy out the results */ if (res.status == (OM_uint32) GSS_S_COMPLETE || res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { /* * if the return code is GSS_S_CONTINUE_NEEDED * ignore all return parameters except for * status codes, output token and context handle. */ *context_handle = *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); *gssd_context_verifier = res.gssd_context_verifier; if (res.status == GSS_S_COMPLETE) { if (actual_mech_type != NULL) { *actual_mech_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); (*actual_mech_type)->length = (OM_UINT32)res.actual_mech_type.GSS_OID_len; (*actual_mech_type)->elements = (void *)MALLOC((*actual_mech_type)->length); (void) memcpy((*actual_mech_type)->elements, (void *)res.actual_mech_type.GSS_OID_val, (*actual_mech_type)->length); } if (ret_flags != NULL) *ret_flags = res.ret_flags; if (time_rec != NULL) *time_rec = res.time_rec; } } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } static struct gss_config default_gc = { { 0, NULL}, NULL, NULL, 0, kgss_unseal_wrapped, NULL, /* kgss_delete_sec_context_wrapped */ kgss_seal_wrapped, NULL, /* kgss_import_sec_context */ kgss_sign_wrapped, kgss_verify_wrapped }; void kgss_free_oid(gss_OID oid) { FREE(oid->elements, oid->length); FREE(oid, sizeof (gss_OID_desc)); } OM_uint32 kgss_init_sec_context( OM_uint32 *minor_status, const gss_cred_id_t claimant_cred_handle, gss_ctx_id_t *context_handle, const gss_name_t target_name, const gss_OID mech_type, int req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token, gss_OID *actual_mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, uid_t uid) { OM_uint32 err; struct kgss_ctx *kctx; gss_OID amt; gssd_cred_id_t gssd_cl_cred_handle; OM_uint32 gssd_cred_verifier; /* * If this is an initial call, we'll need to create the * wrapper struct that contains kernel state information, and * a reference to the handle from gssd. */ if (*context_handle == GSS_C_NO_CONTEXT) { kctx = KGSS_ALLOC(); /* * The default gss-mechanism struct as pointers to * the sign/seal/verify/unseal routines that make * upcalls to gssd. */ kctx->mech = &default_gc; kctx->gssd_ctx = GSSD_NO_CONTEXT; *context_handle = (gss_ctx_id_t)kctx; } else kctx = (struct kgss_ctx *)*context_handle; if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle); gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle); } else { gssd_cl_cred_handle = GSSD_NO_CREDENTIAL; } /* * We need to know the resulting mechanism oid, so allocate * it if the caller won't. */ if (actual_mech_type == NULL) actual_mech_type = &amt; err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle, gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, target_name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, time_rec, uid); if (GSS_ERROR(err)) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; } else if (err == GSS_S_COMPLETE) { /* * Now check if there is a kernel module for this * mechanism OID. If so, set the gss_mechanism structure * in the wrapper context to point to the kernel mech. */ __kgss_reset_mech(&kctx->mech, *actual_mech_type); /* * If the mech oid was allocated for us, free it. */ if (&amt == actual_mech_type) { kgss_free_oid(amt); } } return (err); } static OM_uint32 kgss_accept_sec_context_wrapped( OM_uint32 *minor_status, gssd_ctx_id_t *context_handle, OM_uint32 *gssd_context_verifier, const gssd_cred_id_t verifier_cred_handle, OM_uint32 gssd_cred_verifier, const gss_buffer_t input_token, const gss_channel_bindings_t input_chan_bindings, gss_buffer_t src_name, gss_OID *mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, gss_cred_id_t *delegated_cred_handle, uid_t uid) { CLIENT *clnt; gss_accept_sec_context_arg arg; gss_accept_sec_context_res res; struct kgss_cred *kcred; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_accept_sec_context: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32)uid; arg.context_handle.GSS_CTX_ID_T_len = *context_handle == GSSD_NO_CONTEXT ? 0 : (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = *gssd_context_verifier; arg.verifier_cred_handle.GSS_CRED_ID_T_len = verifier_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.verifier_cred_handle.GSS_CRED_ID_T_val = (char *)&verifier_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.input_token_buffer.GSS_BUFFER_T_len = (uint_t)(input_token != GSS_C_NO_BUFFER ? input_token->length : 0); arg.input_token_buffer.GSS_BUFFER_T_val = (char *)(input_token != GSS_C_NO_BUFFER ? input_token->value : 0); if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { arg.input_chan_bindings.present = YES; arg.input_chan_bindings.initiator_addrtype = input_chan_bindings->initiator_addrtype; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->initiator_address.length; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = (void *)input_chan_bindings->initiator_address.value; arg.input_chan_bindings.acceptor_addrtype = input_chan_bindings->acceptor_addrtype; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->acceptor_address.length; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = (void *)input_chan_bindings->acceptor_address.value; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->application_data.length; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = (void *)input_chan_bindings->application_data.value; } else { arg.input_chan_bindings.present = NO; arg.input_chan_bindings.initiator_addrtype = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.acceptor_addrtype = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; } /* set the return parameters in case of errors.... */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (src_name != NULL) { src_name->length = 0; src_name->value = NULL; } if (mech_type != NULL) *mech_type = NULL; if (output_token != NULL) output_token->length = 0; if (ret_flags != NULL) *ret_flags = 0; if (time_rec != NULL) *time_rec = 0; if (delegated_cred_handle != NULL) *delegated_cred_handle = NULL; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { killgssd_handle(clnt); GSSLOG0(1, "kgss_accept_sec_context: RPC call times out\n"); return (GSS_S_FAILURE); } if (minor_status != NULL) *minor_status = res.minor_status; if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = (void *)MALLOC(output_token->length); (void) memcpy(output_token->value, res.output_token.GSS_BUFFER_T_val, output_token->length); } /* if the call was successful, copy out the results */ if (res.status == (OM_uint32)GSS_S_COMPLETE || res.status == (OM_uint32)GSS_S_CONTINUE_NEEDED) { /* * the only parameters that are ready when we * get GSS_S_CONTINUE_NEEDED are: minor, ctxt_handle, * and the output token to send to the peer. */ *context_handle = *((gssd_ctx_id_t *) res.context_handle.GSS_CTX_ID_T_val); *gssd_context_verifier = res.gssd_context_verifier; /* these other parameters are only ready upon GSS_S_COMPLETE */ if (res.status == (OM_uint32)GSS_S_COMPLETE) { if (src_name != NULL) { src_name->length = res.src_name.GSS_BUFFER_T_len; src_name->value = res.src_name.GSS_BUFFER_T_val; res.src_name.GSS_BUFFER_T_val = NULL; res.src_name.GSS_BUFFER_T_len = 0; } /* * move mech type returned to mech_type * for gss_import_name_for_mech() */ if (mech_type != NULL) { *mech_type = (gss_OID)MALLOC(sizeof (gss_OID_desc)); (*mech_type)->length = (OM_UINT32)res.mech_type.GSS_OID_len; (*mech_type)->elements = (void *)MALLOC((*mech_type)->length); (void) memcpy((*mech_type)->elements, res.mech_type.GSS_OID_val, (*mech_type)->length); } if (ret_flags != NULL) *ret_flags = res.ret_flags; if (time_rec != NULL) *time_rec = res.time_rec; if ((delegated_cred_handle != NULL) && (res.delegated_cred_handle.GSS_CRED_ID_T_len != 0)) { kcred = KGSS_CRED_ALLOC(); kcred->gssd_cred = *((gssd_cred_id_t *) res.delegated_cred_handle.GSS_CRED_ID_T_val); kcred->gssd_cred_verifier = res.gssd_context_verifier; *delegated_cred_handle = (gss_cred_id_t)kcred; } } } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_accept_sec_context( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, const gss_cred_id_t verifier_cred_handle, const gss_buffer_t input_token, const gss_channel_bindings_t input_chan_bindings, gss_buffer_t src_name, gss_OID *mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, gss_cred_id_t *delegated_cred_handle, uid_t uid) { OM_uint32 err; struct kgss_ctx *kctx; gss_OID mt; OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_ver_cred_handle; /* * See kgss_init_sec_context() to get an idea of what is going * on here. */ if (mech_type == NULL) mech_type = &mt; if (*context_handle == GSS_C_NO_CONTEXT) { kctx = KGSS_ALLOC(); kctx->mech = &default_gc; kctx->gssd_ctx = GSSD_NO_CONTEXT; *context_handle = (gss_ctx_id_t)kctx; } else kctx = (struct kgss_ctx *)*context_handle; if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(verifier_cred_handle); gssd_ver_cred_handle = KCRED_TO_CRED(verifier_cred_handle); } else { gssd_ver_cred_handle = GSSD_NO_CREDENTIAL; } err = kgss_accept_sec_context_wrapped(minor_status, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, gssd_ver_cred_handle, gssd_cred_verifier, input_token, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle, uid); if (GSS_ERROR(err)) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; } else if (err == GSS_S_COMPLETE) { __kgss_reset_mech(&kctx->mech, *mech_type); /* * If the mech oid was allocated for us, free it. */ if (&mt == mech_type) { kgss_free_oid(mt); } } return (err); } OM_uint32 kgss_process_context_token(minor_status, context_handle, token_buffer, uid) OM_uint32 *minor_status; const gss_ctx_id_t context_handle; gss_buffer_t token_buffer; uid_t uid; { CLIENT *clnt; OM_uint32 gssd_context_verifier; gssd_ctx_id_t gssd_ctx_handle; gss_process_context_token_arg arg; gss_process_context_token_res res; gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle); gssd_ctx_handle = (gssd_ctx_id_t)KGSS_CTX_TO_GSSD_CTX(context_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_process_context_token: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&gssd_ctx_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; /* call the remote procedure */ bzero(&res, sizeof (res)); if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; GSSLOG0(1, "kgss_process_context_token: RPC call times out\n"); killgssd_handle(clnt); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* return with status returned in rpc call */ killgssd_handle(clnt); return (res.status); } /*ARGSUSED*/ static OM_uint32 kgss_delete_sec_context_wrapped(void *private, OM_uint32 *minor_status, gssd_ctx_id_t *context_handle, gss_buffer_t output_token, OM_uint32 gssd_context_verifier) { CLIENT *clnt; gss_delete_sec_context_arg arg; gss_delete_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_delete_sec_context: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = *context_handle == GSSD_NO_CONTEXT ? 0 : (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = gssd_context_verifier; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (context_handle != NULL) *context_handle = 0; if (output_token != NULL) output_token->length = 0; killgssd_handle(clnt); GSSLOG0(1, "kgssd_delete_sec_context: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.context_handle.GSS_CTX_ID_T_len == 0) *context_handle = 0; else *context_handle = *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); if (output_token != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = res.output_token.GSS_BUFFER_T_val; res.output_token.GSS_BUFFER_T_len = 0; res.output_token.GSS_BUFFER_T_val = NULL; } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_delete_sec_context( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token) { OM_uint32 err; struct kgss_ctx *kctx; if (*context_handle == GSS_C_NO_CONTEXT) { GSSLOG0(8, "kgss_delete_sec_context: Null context handle \n"); return (GSS_S_COMPLETE); } else kctx = (struct kgss_ctx *)*context_handle; if (kctx->ctx_imported == FALSE) { if (kctx->gssd_ctx == GSSD_NO_CONTEXT) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; return (GSS_S_COMPLETE); } err = kgss_delete_sec_context_wrapped( KCTX_TO_PRIVATE(*context_handle), minor_status, &kctx->gssd_ctx, output_token, kctx->gssd_ctx_verifier); } else { if (kctx->gssd_i_ctx == (gss_ctx_id_t)GSS_C_NO_CONTEXT) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; return (GSS_S_COMPLETE); } err = KGSS_DELETE_SEC_CONTEXT(minor_status, kctx, &kctx->gssd_i_ctx, output_token); } KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; return (err); } OM_uint32 kgss_export_sec_context_wrapped(minor_status, context_handle, output_token, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t *context_handle; gss_buffer_t output_token; OM_uint32 gssd_context_verifier; { CLIENT *clnt; gss_export_sec_context_arg arg; gss_export_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_export_sec_context_wrapped :" " can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = gssd_context_verifier; /* call the remote procedure */ (void) memset(&res, 0, sizeof (res)); if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return * GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (context_handle != NULL) *context_handle = 0; if (output_token != NULL) output_token->length = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_export_sec_context_wrapped: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.context_handle.GSS_CTX_ID_T_len == 0) *context_handle = 0; else *context_handle = *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); if (output_token != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = (void *) MALLOC(output_token->length); (void) memcpy(output_token->value, res.output_token.GSS_BUFFER_T_val, output_token->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_export_sec_context(minor_status, context_handle, output_token) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t output_token; { struct kgss_ctx *kctx; if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); else kctx = (struct kgss_ctx *)context_handle; /* * If there is a kernel module then import_sec context must be * supported and we make an upcall to export_sec_context. * If there is no kernel module then we return an error */ *minor_status = 0; if (kctx->mech->gss_import_sec_context) { GSSLOG0(8, "kgss_export_sec_context: Kernel mod available \n"); return (kgss_export_sec_context_wrapped(minor_status, &kctx->gssd_ctx, output_token, kctx->gssd_ctx_verifier)); } else { /* * This is not the right error value; instead of * inventing new error we return GSS_S_NAME_NOT_MN * This error is not returned by the export routine */ GSSLOG0(8, "kgss_export_sec_context: Kernel mod " "unavailable \n"); return (GSS_S_NAME_NOT_MN); } } OM_uint32 kgss_import_sec_context(minor_status, interprocess_token, context_handle) OM_uint32 * minor_status; const gss_buffer_t interprocess_token; gss_ctx_id_t context_handle; { OM_uint32 status; struct kgss_ctx *kctx; size_t length; char *p; gss_buffer_desc token; gss_ctx_id_t internal_ctx_id; kctx = (struct kgss_ctx *)context_handle; if (kctx->gssd_ctx != GSSD_NO_CONTEXT) { return (GSS_S_FAILURE); } if (!(KCTX_TO_MECH(context_handle)->gss_import_sec_context)) { /* * This should never happen * If Kernel import sec context does not exist the export * sec context should have caught this and returned an error * and the caller should not have called this routine */ GSSLOG0(1, "import_sec_context called improperly\n"); return (GSS_S_FAILURE); } *minor_status = 0; if (interprocess_token->length == 0 || interprocess_token->value == 0) return (GSS_S_DEFECTIVE_TOKEN); status = GSS_S_FAILURE; p = interprocess_token->value; length = *p++; length = (length << 8) + *p++; length = (length << 8) + *p++; length = (length << 8) + *p++; p += length; token.length = interprocess_token->length - 4 - length; token.value = p; /* * select the approprate underlying mechanism routine and * call it. */ status = KGSS_IMPORT_SEC_CONTEXT(minor_status, &token, kctx, &internal_ctx_id); if (status == GSS_S_COMPLETE) { KCTX_TO_I_CTX(kctx) = internal_ctx_id; kctx->ctx_imported = TRUE; return (GSS_S_COMPLETE); } else return (status); } /*ARGSUSED*/ OM_uint32 kgss_context_time(minor_status, context_handle, time_rec, uid) OM_uint32 *minor_status; const gss_ctx_id_t context_handle; OM_uint32 *time_rec; uid_t uid; { return (GSS_S_FAILURE); } /*ARGSUSED*/ static OM_uint32 kgss_sign_wrapped(void *private, OM_uint32 *minor_status, const gss_ctx_id_t ctx_handle, int qop_req, const gss_buffer_t message_buffer, gss_buffer_t msg_token, OM_uint32 gssd_context_verifier) { CLIENT *clnt; gssd_ctx_id_t context_handle; gss_sign_arg arg; gss_sign_res res; context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_sign: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.qop_req = qop_req; arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (msg_token != NULL) msg_token->length = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_sign: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (msg_token != NULL) { msg_token->length = res.msg_token.GSS_BUFFER_T_len; msg_token->value = (void *) MALLOC(msg_token->length); (void) memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val, msg_token->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_sign( OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int qop_req, const gss_buffer_t message_buffer, gss_buffer_t msg_token) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_SIGN(minor_status, context_handle, qop_req, message_buffer, msg_token)); } /*ARGSUSED*/ static OM_uint32 kgss_verify_wrapped(void *private, OM_uint32 *minor_status, const gss_ctx_id_t ctx_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, int *qop_state, OM_uint32 gssd_context_verifier) { CLIENT *clnt; gssd_ctx_id_t context_handle; gss_verify_arg arg; gss_verify_res res; context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_verify: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (qop_state != NULL) *qop_state = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_verify: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (qop_state != NULL) *qop_state = res.qop_state; /* return with status returned in rpc call */ killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_verify(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, int *qop_state) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_VERIFY(minor_status, context_handle, message_buffer, token_buffer, qop_state)); } /*ARGSUSED*/ static OM_uint32 kgss_seal_wrapped(void *private, OM_uint32 *minor_status, const gss_ctx_id_t ctx_handle, int conf_req_flag, int qop_req, const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer, OM_uint32 gssd_context_verifier) { CLIENT *clnt; gssd_ctx_id_t context_handle; gss_seal_arg arg; gss_seal_res res; context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_seal: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (OM_uint32); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.conf_req_flag = conf_req_flag; arg.qop_req = qop_req; arg.input_message_buffer.GSS_BUFFER_T_len = (uint_t)input_message_buffer->length; arg.input_message_buffer.GSS_BUFFER_T_val = (char *)input_message_buffer->value; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (conf_state != NULL) *conf_state = 0; if (output_message_buffer != NULL) output_message_buffer->length = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_seal: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (conf_state != NULL) *conf_state = res.conf_state; if (output_message_buffer != NULL) { output_message_buffer->length = res.output_message_buffer.GSS_BUFFER_T_len; output_message_buffer->value = (void *) MALLOC(output_message_buffer->length); (void) memcpy(output_message_buffer->value, res.output_message_buffer.GSS_BUFFER_T_val, output_message_buffer->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } /*ARGSUSED*/ OM_uint32 kgss_seal(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, int qop_req, const gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_SEAL(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer)); } /*ARGSUSED*/ static OM_uint32 kgss_unseal_wrapped(void *private, OM_uint32 *minor_status, const gss_ctx_id_t ctx_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int *conf_state, int *qop_state, OM_uint32 gssd_context_verifier) { CLIENT *clnt; gss_unseal_arg arg; gss_unseal_res res; gssd_ctx_id_t context_handle; context_handle = (gssd_ctx_id_t)KCTX_TO_GSSD_CTX(ctx_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_unseal: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.input_message_buffer.GSS_BUFFER_T_len = (uint_t)input_message_buffer->length; arg.input_message_buffer.GSS_BUFFER_T_val = (char *)input_message_buffer->value; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (output_message_buffer != NULL) output_message_buffer->length = 0; if (conf_state != NULL) *conf_state = 0; if (qop_state != NULL) *qop_state = 0; killgssd_handle(clnt); GSSLOG0(1, "kgss_unseal: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_message_buffer != NULL) { output_message_buffer->length = res.output_message_buffer.GSS_BUFFER_T_len; output_message_buffer->value = (void *) MALLOC(output_message_buffer->length); (void) memcpy(output_message_buffer->value, res.output_message_buffer.GSS_BUFFER_T_val, output_message_buffer->length); } if (conf_state != NULL) *conf_state = res.conf_state; if (qop_state != NULL) *qop_state = res.qop_state; /* * free the memory allocated for the results and return with the * status received in the rpc call */ clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_unseal(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t input_message_buffer, const gss_buffer_t output_message_buffer, int *conf_state, int *qop_state) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_UNSEAL(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state)); } OM_uint32 kgss_display_status(minor_status, status_value, status_type, mech_type, message_context, status_string, uid) OM_uint32 *minor_status; OM_uint32 status_value; int status_type; const gss_OID mech_type; int *message_context; gss_buffer_t status_string; uid_t uid; { CLIENT *clnt; gss_display_status_arg arg; gss_display_status_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_display_status: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.status_value = status_value; arg.status_type = status_type; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); arg.message_context = *message_context; /* call the remote procedure */ if (message_context != NULL) *message_context = 0; if (status_string != NULL) { status_string->length = 0; status_string->value = NULL; } bzero((caddr_t)&res, sizeof (res)); if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; killgssd_handle(clnt); GSSLOG0(1, "kgss_display_status: RPC call time out\n"); return (GSS_S_FAILURE); } /* now process the results and pass them back to the caller */ if (res.status == GSS_S_COMPLETE) { if (minor_status != NULL) *minor_status = res.minor_status; if (message_context != NULL) *message_context = res.message_context; if (status_string != NULL) { status_string->length = (size_t)res.status_string.GSS_BUFFER_T_len; status_string->value = (void *) MALLOC(status_string->length); (void) memcpy(status_string->value, res.status_string.GSS_BUFFER_T_val, status_string->length); } } clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } /*ARGSUSED*/ OM_uint32 kgss_indicate_mechs(minor_status, mech_set, uid) OM_uint32 *minor_status; gss_OID_set *mech_set; uid_t uid; { CLIENT *clnt; void *arg; gss_indicate_mechs_res res; int i; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_indicate_mechs: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } bzero((caddr_t)&res, sizeof (res)); if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (mech_set != NULL) *mech_set = NULL; killgssd_handle(clnt); GSSLOG0(1, "kgss_indicate_mechs: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (mech_set != NULL) { *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*mech_set)->count = res.mech_set.GSS_OID_SET_len; (*mech_set)->elements = (void *) MALLOC ((*mech_set)->count * sizeof (gss_OID_desc)); for (i = 0; i < (*mech_set)->count; i++) { (*mech_set)->elements[i].length = res.mech_set.GSS_OID_SET_val[i].GSS_OID_len; (*mech_set)->elements[i].elements = (void *) MALLOC ((*mech_set)->elements[i].length); (void) memcpy((*mech_set)->elements[i].elements, res.mech_set.GSS_OID_SET_val[i].GSS_OID_val, (*mech_set)->elements[i].length); } } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_inquire_cred_wrapped(minor_status, cred_handle, gssd_cred_verifier, name, lifetime, cred_usage, mechanisms, uid) OM_uint32 *minor_status; const gssd_cred_id_t cred_handle; OM_uint32 gssd_cred_verifier; gss_name_t *name; OM_uint32 *lifetime; int *cred_usage; gss_OID_set *mechanisms; uid_t uid; { CLIENT *clnt; OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID_desc name_type; int i; gss_inquire_cred_arg arg; gss_inquire_cred_res res; /* * NULL the params here once * If there are errors then we won't * have to do it for every error * case */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (name != NULL) *name = NULL; if (lifetime != NULL) *lifetime = 0; if (cred_usage != NULL) *cred_usage = 0; if (mechanisms != NULL) *mechanisms = NULL; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.cred_handle.GSS_CRED_ID_T_len = cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out * kill the handle and return GSS_S_FAILURE * the parameters have been set to NULL already */ killgssd_handle(clnt); GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* convert name from external to internal format */ if (name != NULL) { external_name.length = res.name.GSS_BUFFER_T_len; external_name.value = res.name.GSS_BUFFER_T_val; /* * we can pass a pointer to res structure * since gss_import_name treats the name_type * parameter as read only and performs a copy */ name_type.length = res.name_type.GSS_OID_len; name_type.elements = (void *)res.name_type.GSS_OID_val; if (gss_import_name(&minor_status_temp, &external_name, &name_type, name) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); killgssd_handle(clnt); GSSLOG0(1, "kgss_inquire_cred: import name fails\n"); return ((OM_uint32) GSS_S_FAILURE); } } if (lifetime != NULL) *lifetime = res.lifetime; if (cred_usage != NULL) *cred_usage = res.cred_usage; if (res.status == GSS_S_COMPLETE && res.mechanisms.GSS_OID_SET_len != 0 && mechanisms != NULL) { *mechanisms = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*mechanisms)->count = (int)res.mechanisms.GSS_OID_SET_len; (*mechanisms)->elements = (gss_OID) MALLOC(sizeof (gss_OID_desc) * (*mechanisms)->count); for (i = 0; i < (*mechanisms)->count; i++) { (*mechanisms)->elements[i].length = (OM_uint32) res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len; (*mechanisms)->elements[i].elements = (void *) MALLOC((*mechanisms)->elements[i].length); (void) memcpy((*mechanisms)->elements[i].elements, res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val, (*mechanisms)->elements[i].length); } } else { if (res.status == GSS_S_COMPLETE && mechanisms != NULL) (*mechanisms) = NULL; } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_inquire_cred(minor_status, cred_handle, name, lifetime, cred_usage, mechanisms, uid) OM_uint32 *minor_status; const gss_cred_id_t cred_handle; gss_name_t *name; OM_uint32 *lifetime; int *cred_usage; gss_OID_set * mechanisms; uid_t uid; { OM_uint32 gssd_cred_verifier; OM_uint32 gssd_cred_handle; gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); gssd_cred_handle = KCRED_TO_CRED(cred_handle); return (kgss_inquire_cred_wrapped(minor_status, gssd_cred_handle, gssd_cred_verifier, name, lifetime, cred_usage, mechanisms, uid)); } OM_uint32 kgss_inquire_cred_by_mech_wrapped(minor_status, cred_handle, gssd_cred_verifier, mech_type, uid) OM_uint32 *minor_status; gssd_cred_id_t cred_handle; OM_uint32 gssd_cred_verifier; gss_OID mech_type; uid_t uid; { CLIENT *clnt; gss_inquire_cred_by_mech_arg arg; gss_inquire_cred_by_mech_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_inquire_cred: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.cred_handle.GSS_CRED_ID_T_len = cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set * minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; killgssd_handle(clnt); GSSLOG0(1, "kgss_inquire_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res); killgssd_handle(clnt); return (res.status); } OM_uint32 kgss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, uid) OM_uint32 *minor_status; gss_cred_id_t cred_handle; gss_OID mech_type; uid_t uid; { OM_uint32 gssd_cred_verifier; OM_uint32 gssd_cred_handle; gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); gssd_cred_handle = KCRED_TO_CRED(cred_handle); return (kgss_inquire_cred_by_mech_wrapped(minor_status, gssd_cred_handle, gssd_cred_verifier, mech_type, uid)); } OM_uint32 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid) const gss_buffer_t expName; uid_t *uidOut; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { CLIENT *clnt; gsscred_expname_to_unix_cred_arg args; gsscred_expname_to_unix_cred_res res; /* check input/output parameters */ if (expName == NULL || expName->value == NULL) return (GSS_S_CALL_INACCESSIBLE_READ); if (uidOut == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* NULL out output parameters */ *uidOut = UID_NOBODY; if (gidsLen) *gidsLen = 0; if (gids) *gids = NULL; /* get the client handle to gssd */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgsscred_expname_to_unix_cred:" " can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* copy the procedure arguments */ args.uid = uid; args.expname.GSS_BUFFER_T_val = expName->value; args.expname.GSS_BUFFER_T_len = expName->length; /* null out the return buffer and call the remote proc */ bzero(&res, sizeof (res)); if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) { killgssd_handle(clnt); GSSLOG0(1, "kgsscred_expname_to_unix_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the results into the result parameters */ if (res.major == GSS_S_COMPLETE) { *uidOut = res.uid; if (gidOut) *gidOut = res.gid; if (gids && gidsLen) { *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } } /* free RPC results */ clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res); killgssd_handle(clnt); return (res.major); } /* kgsscred_expname_to_unix_cred */ OM_uint32 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, gidsLen, uid) const gss_name_t intName; const gss_OID mechType; uid_t *uidOut; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { CLIENT *clnt; gsscred_name_to_unix_cred_arg args; gsscred_name_to_unix_cred_res res; OM_uint32 major, minor; gss_OID nameOid; gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER; /* check the input/output parameters */ if (intName == NULL || mechType == NULL) return (GSS_S_CALL_INACCESSIBLE_READ); if (uidOut == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* NULL out the output parameters */ *uidOut = UID_NOBODY; if (gids) *gids = NULL; if (gidsLen) *gidsLen = 0; /* get the client handle to gssd */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgsscred_name_to_unix_cred: can't connect to server %s\n", server); return (GSS_S_FAILURE); } /* convert the name to flat representation */ if ((major = gss_display_name(&minor, intName, &flatName, &nameOid)) != GSS_S_COMPLETE) { killgssd_handle(clnt); GSSLOG0(1, "kgsscred_name_to_unix_cred: display name failed\n"); return (major); } /* set the rpc parameters */ args.uid = uid; args.pname.GSS_BUFFER_T_len = flatName.length; args.pname.GSS_BUFFER_T_val = flatName.value; args.name_type.GSS_OID_len = nameOid->length; args.name_type.GSS_OID_val = nameOid->elements; args.mech_type.GSS_OID_len = mechType->length; args.mech_type.GSS_OID_val = mechType->elements; /* call the remote procedure */ bzero(&res, sizeof (res)); if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) { killgssd_handle(clnt); (void) gss_release_buffer(&minor, &flatName); GSSLOG0(1, "kgsscred_name_to_unix_cred: RPC call times out\n"); return (GSS_S_FAILURE); } /* delete the flat name buffer */ (void) gss_release_buffer(&minor, &flatName); /* copy the output parameters on output */ if (res.major == GSS_S_COMPLETE) { *uidOut = res.uid; if (gidOut) *gidOut = res.gid; if (gids && gidsLen) { *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } } /* delete RPC allocated memory */ clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res); killgssd_handle(clnt); return (res.major); } /* kgsscred_name_to_unix_cred */ OM_uint32 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid) const uid_t puid; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { CLIENT *clnt; gss_get_group_info_arg args; gss_get_group_info_res res; /* check the output parameters */ if (gidOut == NULL || gids == NULL || gidsLen == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* get the client GSSD handle */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_get_group_info: can't connect to server on %s\n", server); return (GSS_S_FAILURE); } /* set the input parameters */ args.uid = uid; args.puid = puid; /* call the remote procedure */ bzero(&res, sizeof (res)); if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) { killgssd_handle(clnt); GSSLOG0(1, "kgss_get_group_info: RPC call times out\n"); return (GSS_S_FAILURE); } /* copy the results */ if (res.major == GSS_S_COMPLETE) { *gidOut = res.gid; *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } /* no results to free */ killgssd_handle(clnt); return (res.major); } /* kgss_get_group_info */ static char * kgss_get_kmod(gss_OID mech_oid) { CLIENT *clnt; gss_get_kmod_arg args; gss_get_kmod_res res; /* get the client GSSD handle */ if ((clnt = getgssd_handle()) == NULL) { GSSLOG(1, "kgss_get_kmod: can't connect to server on %s\n", server); return (NULL); } /* set the input parameters */ args.mech_oid.GSS_OID_len = mech_oid->length; args.mech_oid.GSS_OID_val = mech_oid->elements; /* call the remote procedure */ bzero(&res, sizeof (res)); if (gss_get_kmod_1(&args, &res, clnt) != RPC_SUCCESS) { killgssd_handle(clnt); GSSLOG0(1, "gss_get_kmod_1: RPC call times out\n"); return (NULL); } /* no results to free */ killgssd_handle(clnt); if (res.module_follow == TRUE) { return (res.gss_get_kmod_res_u.modname); } else return (NULL); } /* kgss_get_kmod */ static gss_mechanism kgss_mech_head; static gss_mechanism kgss_mech_tail; kmutex_t __kgss_mech_lock; /* * See if there is kernel mechanism module, and if so, attempt to * load it and reset the pointer (gss_mechanism) to the sign/seal/etc. * entry points to that of the kernel module. */ static void __kgss_reset_mech(gss_mechanism *mechp, gss_OID mech_oid) { gss_mechanism mech; char *kmod; /* * We can search the list without a mutex, becuase the list never * shrinks and we always add to the end. */ mech = __kgss_get_mechanism(mech_oid); if (mech) { *mechp = mech; return; } /* * Get the module name from the kernel. */ kmod = kgss_get_kmod(mech_oid); if (kmod) { extern int modload(const char *, const char *); if (modload("misc/kgss", kmod) < 0) { /* * Modload of 'kmod' failed, so log an * appropriate comment */ cmn_err(CE_NOTE, "kgss_reset_mech: Algorithm modload " "(%s) failed. Userland gssd will now handle " "all GSSAPI calls, which may result in " "reduced performance.\n", kmod); }; /* * Allocated in the XDR routine called by gss_get_kmod_1(). */ FREE(kmod, strlen(kmod)+1); mech = __kgss_get_mechanism(mech_oid); if (mech) { *mechp = mech; } /* * If for some reason the module load didn't take, * we return anyway and hope that the next context * creation succeeds. */ return; } /* * No kernel module, so enter this mech oid into the list * using the default sign/seal/etc. operations that upcall to * gssd. */ mutex_enter(&__kgss_mech_lock); mech = __kgss_get_mechanism(mech_oid); if (mech) { mutex_exit(&__kgss_mech_lock); *mechp = mech; return; } /* * Allocate space for the mechanism entry. */ mech = kmem_zalloc(sizeof (struct gss_config), KM_SLEEP); /* * Copy basic information from default mechanism struct. */ *mech = default_gc; /* * Record the real mech OID. */ mech->mech_type.length = mech_oid->length; mech->mech_type.elements = MALLOC(mech_oid->length); bcopy(mech_oid->elements, mech->mech_type.elements, mech_oid->length); /* * Add it to the table. */ __kgss_add_mechanism(mech); mutex_exit(&__kgss_mech_lock); *mechp = mech; } /* * Called with __kgss_mech_lock held. */ void __kgss_add_mechanism(gss_mechanism mech) { gss_mechanism tmp; tmp = kgss_mech_tail; kgss_mech_tail = mech; if (tmp != NULL) tmp->next = mech; if (kgss_mech_head == NULL) kgss_mech_head = mech; } /* * given the mechs_array and a mechanism OID, return the * pointer to the mechanism, or NULL if that mechanism is * not supported. */ gss_mechanism __kgss_get_mechanism(gss_OID type) { gss_mechanism mech; mech = kgss_mech_head; /* * Note that a reader can scan this list without the mutex held. * This is safe because we always append, and never shrink the list. * Moreover, the entry is fully initialized before it is ever * added to the list. */ while (mech != NULL) { if ((mech->mech_type.length == type->length) && (bcmp(mech->mech_type.elements, type->elements, type->length) == 0)) return (mech); mech = mech->next; } return (NULL); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Kernel code to obtain client handle to gssd server */ #include #include #include #include #include #include #include #include #define GSSD_RETRY 5 kmutex_t gssrpcb_lock; zone_key_t gss_zone_key; struct gss_globals { enum clnt_stat gss_last_stat; struct netbuf gss_netaddr; struct knetconfig gss_config; }; /* ARGSUSED */ void * gss_zone_init(zoneid_t zoneid) { struct gss_globals *gssg; gssg = kmem_zalloc(sizeof (*gssg), KM_SLEEP); return (gssg); } /* ARGSUSED */ void gss_zone_fini(zoneid_t zoneid, void *data) { struct gss_globals *gssg = data; struct netbuf *netaddrp = &gssg->gss_netaddr; if (netaddrp->len != 0) kmem_free(netaddrp->buf, netaddrp->maxlen); kmem_free(gssg, sizeof (*gssg)); } void killgssd_handle(CLIENT *client) { struct rpc_err rpcerr; struct gss_globals *gssg; gssg = zone_getspecific(gss_zone_key, curproc->p_zone); CLNT_GETERR(client, &rpcerr); gssg->gss_last_stat = rpcerr.re_status; AUTH_DESTROY(client->cl_auth); CLNT_DESTROY(client); } CLIENT * getgssd_handle(void) { struct vnode *vp; int error; CLIENT *clnt; enum clnt_stat stat; struct netbuf tmpaddr; struct gss_globals *gssg; struct netbuf *netaddrp; gssg = zone_getspecific(gss_zone_key, curproc->p_zone); /* * Cribbed from kerb_krpc.c. Really should do the config set up * in the _init routine. */ if (gssg->gss_config.knc_rdev == 0) { if ((error = lookupname("/dev/ticotsord", UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0) { GSSLOG(1, "getgssd_handle: lookupname: %d\n", error); return (NULL); } gssg->gss_config.knc_rdev = vp->v_rdev; gssg->gss_config.knc_protofmly = loopback_name; VN_RELE(vp); gssg->gss_config.knc_semantics = NC_TPI_COTS_ORD; } /* * Contact rpcbind to get gssd's address only * once and re-use the address. */ mutex_enter(&gssrpcb_lock); netaddrp = &gssg->gss_netaddr; if (netaddrp->len == 0 || gssg->gss_last_stat != RPC_SUCCESS) { if (netaddrp->buf != NULL) kmem_free(netaddrp->buf, netaddrp->maxlen); /* Set up netaddr to be "localhost." (strlen is 10) */ netaddrp->len = netaddrp->maxlen = 10; netaddrp->buf = kmem_alloc(netaddrp->len, KM_SLEEP); (void) strncpy(netaddrp->buf, "localhost.", netaddrp->len); /* Get address of gssd from rpcbind */ stat = rpcbind_getaddr(&gssg->gss_config, GSSPROG, GSSVERS, netaddrp); if (stat != RPC_SUCCESS) { kmem_free(netaddrp->buf, netaddrp->maxlen); netaddrp->buf = NULL; netaddrp->len = netaddrp->maxlen = 0; mutex_exit(&gssrpcb_lock); return (NULL); } } /* * Copy the netaddr information into a tmp location to * be used by clnt_tli_kcreate. The purpose of this * is for MT race condition (ie. netaddr being modified * while it is being used.) */ tmpaddr.buf = kmem_zalloc(netaddrp->maxlen, KM_SLEEP); bcopy(netaddrp->buf, tmpaddr.buf, netaddrp->maxlen); tmpaddr.maxlen = netaddrp->maxlen; tmpaddr.len = netaddrp->len; mutex_exit(&gssrpcb_lock); error = clnt_tli_kcreate(&gssg->gss_config, &tmpaddr, GSSPROG, GSSVERS, 0, GSSD_RETRY, kcred, &clnt); kmem_free(tmpaddr.buf, tmpaddr.maxlen); if (error != 0) { GSSLOG(1, "getgssd_handle: clnt_tli_kcreate: error %d\n", error); return (NULL); } return (clnt); } /* * Please do not edit this file. * It was generated using rpcgen. */ #include "gssd_prot.h" #ifndef _KERNEL #endif /* !_KERNEL */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * RPC protocol information for gssd, the usermode daemon that * assists the kernel with gssapi. It is gssd that executes all * gssapi calls except for some such as gss_sign(), and * gss_verify(), which are executed in the kernel itself. * * File generated from gssd.x */ #define NO 0 #define YES 1 #define FOREVER 1 #include #include #include #ifndef _KERNEL #include #endif /* not _KERNEL */ #ifdef _KERNEL extern void killgssd_handle(CLIENT *); extern CLIENT *getgssd_handle(void); #endif /* _KERNEL */ /* gss_indicate_mechs_arg is void. This appears in the rpc call def */ /* Default timeout can be changed using clnt_control() */ static struct timeval gssd_timeout = { 125, 0 }; enum clnt_stat gss_acquire_cred_1(argp, clnt_res, clnt) gss_acquire_cred_arg *argp; gss_acquire_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_ACQUIRE_CRED, (xdrproc_t)xdr_gss_acquire_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_acquire_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_release_cred_1(argp, clnt_res, clnt) gss_release_cred_arg *argp; gss_release_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_RELEASE_CRED, (xdrproc_t)xdr_gss_release_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_release_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_init_sec_context_1(argp, clnt_res, clnt) gss_init_sec_context_arg *argp; gss_init_sec_context_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_INIT_SEC_CONTEXT, (xdrproc_t)xdr_gss_init_sec_context_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_init_sec_context_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_accept_sec_context_1(argp, clnt_res, clnt) gss_accept_sec_context_arg *argp; gss_accept_sec_context_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_ACCEPT_SEC_CONTEXT, (xdrproc_t)xdr_gss_accept_sec_context_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_accept_sec_context_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_process_context_token_1(argp, clnt_res, clnt) gss_process_context_token_arg *argp; gss_process_context_token_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_PROCESS_CONTEXT_TOKEN, (xdrproc_t)xdr_gss_process_context_token_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_process_context_token_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_delete_sec_context_1(argp, clnt_res, clnt) gss_delete_sec_context_arg *argp; gss_delete_sec_context_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_DELETE_SEC_CONTEXT, (xdrproc_t)xdr_gss_delete_sec_context_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_delete_sec_context_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_context_time_1(argp, clnt_res, clnt) gss_context_time_arg *argp; gss_context_time_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_CONTEXT_TIME, (xdrproc_t)xdr_gss_context_time_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_context_time_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_sign_1(argp, clnt_res, clnt) gss_sign_arg *argp; gss_sign_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_SIGN, (xdrproc_t)xdr_gss_sign_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_sign_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_verify_1(argp, clnt_res, clnt) gss_verify_arg *argp; gss_verify_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_VERIFY, (xdrproc_t)xdr_gss_verify_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_verify_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_display_status_1(argp, clnt_res, clnt) gss_display_status_arg *argp; gss_display_status_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_DISPLAY_STATUS, (xdrproc_t)xdr_gss_display_status_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_display_status_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_indicate_mechs_1(argp, clnt_res, clnt) void *argp; gss_indicate_mechs_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_INDICATE_MECHS, (xdrproc_t)xdr_void, (caddr_t)argp, (xdrproc_t)xdr_gss_indicate_mechs_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_inquire_cred_1(argp, clnt_res, clnt) gss_inquire_cred_arg *argp; gss_inquire_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_INQUIRE_CRED, (xdrproc_t)xdr_gss_inquire_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_inquire_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_seal_1(argp, clnt_res, clnt) gss_seal_arg *argp; gss_seal_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_SEAL, (xdrproc_t)xdr_gss_seal_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_seal_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_unseal_1(argp, clnt_res, clnt) gss_unseal_arg *argp; gss_unseal_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_UNSEAL, (xdrproc_t)xdr_gss_unseal_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_unseal_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gsscred_expname_to_unix_cred_1(argp, clnt_res, clnt) gsscred_expname_to_unix_cred_arg *argp; gsscred_expname_to_unix_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSSCRED_EXPNAME_TO_UNIX_CRED, (xdrproc_t)xdr_gsscred_expname_to_unix_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gsscred_expname_to_unix_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gsscred_name_to_unix_cred_1(argp, clnt_res, clnt) gsscred_name_to_unix_cred_arg *argp; gsscred_name_to_unix_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSSCRED_NAME_TO_UNIX_CRED, (xdrproc_t)xdr_gsscred_name_to_unix_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gsscred_name_to_unix_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_get_group_info_1(argp, clnt_res, clnt) gss_get_group_info_arg *argp; gss_get_group_info_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_GET_GROUP_INFO, (xdrproc_t)xdr_gss_get_group_info_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_get_group_info_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_get_kmod_1(argp, clnt_res, clnt) gss_get_kmod_arg *argp; gss_get_kmod_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_GET_KMOD, (xdrproc_t)xdr_gss_get_kmod_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_get_kmod_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_export_sec_context_1(argp, clnt_res, clnt) gss_export_sec_context_arg *argp; gss_export_sec_context_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_EXPORT_SEC_CONTEXT, (xdrproc_t)xdr_gss_export_sec_context_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_export_sec_context_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_import_sec_context_1(argp, clnt_res, clnt) gss_import_sec_context_arg *argp; gss_import_sec_context_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_IMPORT_SEC_CONTEXT, (xdrproc_t)xdr_gss_import_sec_context_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_import_sec_context_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_add_cred_1(argp, clnt_res, clnt) gss_add_cred_arg *argp; gss_add_cred_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_ADD_CRED, (xdrproc_t)xdr_gss_add_cred_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_add_cred_res, (caddr_t)clnt_res, gssd_timeout)); } enum clnt_stat gss_inquire_cred_by_mech_1(argp, clnt_res, clnt) gss_inquire_cred_by_mech_arg *argp; gss_inquire_cred_by_mech_res *clnt_res; CLIENT *clnt; { return (clnt_call(clnt, GSS_INQUIRE_CRED_BY_MECH, (xdrproc_t)xdr_gss_inquire_cred_by_mech_arg, (caddr_t)argp, (xdrproc_t)xdr_gss_inquire_cred_by_mech_res, (caddr_t)clnt_res, gssd_timeout)); } /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _GSSD_H_RPCGEN #define _GSSD_H_RPCGEN #include #ifndef _KERNEL #include #include #endif /* !_KERNEL */ #ifdef __cplusplus extern "C" { #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * RPC protocol information for gssd, the usermode daemon that * assists the kernel with gssapi. It is gssd that executes all * gssapi calls except for some such as gss_sign(), and * gss_verify(), which are executed in the kernel itself. * * File generated from gssd.x */ #define NO 0 #define YES 1 #define FOREVER 1 #include #include #include #ifndef _KERNEL #include #endif /* not _KERNEL */ #ifdef _KERNEL extern void killgssd_handle(CLIENT *); extern CLIENT *getgssd_handle(void); #endif /* _KERNEL */ typedef u_int OM_UINT32; typedef struct { u_int GSS_CTX_ID_T_len; char *GSS_CTX_ID_T_val; } GSS_CTX_ID_T; typedef struct { u_int GSS_CRED_ID_T_len; char *GSS_CRED_ID_T_val; } GSS_CRED_ID_T; typedef struct { u_int GSS_OID_len; char *GSS_OID_val; } GSS_OID; typedef struct { u_int GSS_BUFFER_T_len; char *GSS_BUFFER_T_val; } GSS_BUFFER_T; typedef struct { u_int GSSCRED_GIDS_len; gid_t *GSSCRED_GIDS_val; } GSSCRED_GIDS; typedef struct { u_int GSS_OID_SET_len; GSS_OID *GSS_OID_SET_val; } GSS_OID_SET; struct GSS_CHANNEL_BINDINGS_STRUCT { int present; OM_UINT32 initiator_addrtype; GSS_BUFFER_T initiator_address; OM_UINT32 acceptor_addrtype; GSS_BUFFER_T acceptor_address; GSS_BUFFER_T application_data; }; typedef struct GSS_CHANNEL_BINDINGS_STRUCT GSS_CHANNEL_BINDINGS_STRUCT; typedef GSS_CHANNEL_BINDINGS_STRUCT GSS_CHANNEL_BINDINGS; struct gss_acquire_cred_arg { uid_t uid; GSS_BUFFER_T desired_name; GSS_OID name_type; OM_UINT32 time_req; GSS_OID_SET desired_mechs; int cred_usage; }; typedef struct gss_acquire_cred_arg gss_acquire_cred_arg; struct gss_acquire_cred_res { OM_UINT32 minor_status; GSS_CRED_ID_T output_cred_handle; OM_UINT32 gssd_cred_verifier; GSS_OID_SET actual_mechs; OM_UINT32 time_rec; OM_UINT32 status; }; typedef struct gss_acquire_cred_res gss_acquire_cred_res; struct gss_add_cred_arg { uid_t uid; GSS_CRED_ID_T input_cred_handle; OM_UINT32 gssd_cred_verifier; GSS_BUFFER_T desired_name; GSS_OID name_type; GSS_OID desired_mech_type; int cred_usage; OM_UINT32 initiator_time_req; OM_UINT32 acceptor_time_req; }; typedef struct gss_add_cred_arg gss_add_cred_arg; struct gss_add_cred_res { OM_UINT32 minor_status; GSS_OID_SET actual_mechs; OM_UINT32 initiator_time_rec; OM_UINT32 acceptor_time_rec; OM_UINT32 status; }; typedef struct gss_add_cred_res gss_add_cred_res; struct gss_release_cred_arg { uid_t uid; OM_UINT32 gssd_cred_verifier; GSS_CRED_ID_T cred_handle; }; typedef struct gss_release_cred_arg gss_release_cred_arg; struct gss_release_cred_res { OM_UINT32 minor_status; OM_UINT32 status; }; typedef struct gss_release_cred_res gss_release_cred_res; struct gss_init_sec_context_arg { uid_t uid; GSS_CTX_ID_T context_handle; OM_UINT32 gssd_context_verifier; GSS_CRED_ID_T claimant_cred_handle; OM_UINT32 gssd_cred_verifier; GSS_BUFFER_T target_name; GSS_OID name_type; GSS_OID mech_type; int req_flags; OM_UINT32 time_req; GSS_CHANNEL_BINDINGS input_chan_bindings; GSS_BUFFER_T input_token; }; typedef struct gss_init_sec_context_arg gss_init_sec_context_arg; struct gss_init_sec_context_res { GSS_CTX_ID_T context_handle; OM_UINT32 gssd_context_verifier; OM_UINT32 minor_status; GSS_OID actual_mech_type; GSS_BUFFER_T output_token; OM_UINT32 ret_flags; OM_UINT32 time_rec; OM_UINT32 status; }; typedef struct gss_init_sec_context_res gss_init_sec_context_res; struct gss_accept_sec_context_arg { uid_t uid; GSS_CTX_ID_T context_handle; OM_UINT32 gssd_context_verifier; GSS_CRED_ID_T verifier_cred_handle; OM_UINT32 gssd_cred_verifier; GSS_BUFFER_T input_token_buffer; GSS_CHANNEL_BINDINGS input_chan_bindings; }; typedef struct gss_accept_sec_context_arg gss_accept_sec_context_arg; struct gss_accept_sec_context_res { GSS_CTX_ID_T context_handle; OM_UINT32 gssd_context_verifier; OM_UINT32 minor_status; GSS_BUFFER_T src_name; GSS_OID mech_type; GSS_BUFFER_T output_token; OM_UINT32 ret_flags; OM_UINT32 time_rec; GSS_CRED_ID_T delegated_cred_handle; OM_UINT32 status; }; typedef struct gss_accept_sec_context_res gss_accept_sec_context_res; struct gss_process_context_token_arg { uid_t uid; OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; GSS_BUFFER_T token_buffer; }; typedef struct gss_process_context_token_arg gss_process_context_token_arg; struct gss_process_context_token_res { OM_UINT32 minor_status; OM_UINT32 status; }; typedef struct gss_process_context_token_res gss_process_context_token_res; struct gss_delete_sec_context_arg { OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; }; typedef struct gss_delete_sec_context_arg gss_delete_sec_context_arg; struct gss_delete_sec_context_res { OM_UINT32 minor_status; GSS_CTX_ID_T context_handle; GSS_BUFFER_T output_token; OM_UINT32 status; }; typedef struct gss_delete_sec_context_res gss_delete_sec_context_res; struct gss_export_sec_context_arg { GSS_CTX_ID_T context_handle; OM_UINT32 gssd_context_verifier; }; typedef struct gss_export_sec_context_arg gss_export_sec_context_arg; struct gss_export_sec_context_res { OM_UINT32 minor_status; GSS_CTX_ID_T context_handle; GSS_BUFFER_T output_token; OM_UINT32 status; }; typedef struct gss_export_sec_context_res gss_export_sec_context_res; struct gss_import_sec_context_arg { GSS_BUFFER_T input_token; OM_UINT32 gssd_context_verifier; }; typedef struct gss_import_sec_context_arg gss_import_sec_context_arg; struct gss_import_sec_context_res { OM_UINT32 minor_status; GSS_CTX_ID_T context_handle; OM_UINT32 status; }; typedef struct gss_import_sec_context_res gss_import_sec_context_res; struct gss_context_time_arg { uid_t uid; OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; }; typedef struct gss_context_time_arg gss_context_time_arg; struct gss_context_time_res { OM_UINT32 minor_status; OM_UINT32 time_rec; OM_UINT32 status; }; typedef struct gss_context_time_res gss_context_time_res; struct gss_sign_arg { OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; int qop_req; GSS_BUFFER_T message_buffer; }; typedef struct gss_sign_arg gss_sign_arg; struct gss_sign_res { OM_UINT32 minor_status; GSS_BUFFER_T msg_token; OM_UINT32 status; }; typedef struct gss_sign_res gss_sign_res; struct gss_verify_arg { OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; GSS_BUFFER_T message_buffer; GSS_BUFFER_T token_buffer; }; typedef struct gss_verify_arg gss_verify_arg; struct gss_verify_res { OM_UINT32 minor_status; int qop_state; OM_UINT32 status; }; typedef struct gss_verify_res gss_verify_res; struct gss_seal_arg { OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; int conf_req_flag; int qop_req; GSS_BUFFER_T input_message_buffer; }; typedef struct gss_seal_arg gss_seal_arg; struct gss_seal_res { OM_UINT32 minor_status; int conf_state; GSS_BUFFER_T output_message_buffer; OM_UINT32 status; }; typedef struct gss_seal_res gss_seal_res; struct gss_unseal_arg { OM_UINT32 gssd_context_verifier; GSS_CTX_ID_T context_handle; GSS_BUFFER_T input_message_buffer; }; typedef struct gss_unseal_arg gss_unseal_arg; struct gss_unseal_res { OM_UINT32 minor_status; GSS_BUFFER_T output_message_buffer; int conf_state; int qop_state; OM_UINT32 status; }; typedef struct gss_unseal_res gss_unseal_res; struct gss_display_status_arg { uid_t uid; int status_value; int status_type; GSS_OID mech_type; OM_UINT32 message_context; }; typedef struct gss_display_status_arg gss_display_status_arg; struct gss_display_status_res { OM_UINT32 minor_status; int message_context; GSS_BUFFER_T status_string; OM_UINT32 status; }; typedef struct gss_display_status_res gss_display_status_res; /* gss_indicate_mechs_arg is void. This appears in the rpc call def */ struct gss_indicate_mechs_res { OM_UINT32 minor_status; GSS_OID_SET mech_set; OM_UINT32 status; }; typedef struct gss_indicate_mechs_res gss_indicate_mechs_res; struct gss_inquire_cred_arg { uid_t uid; OM_UINT32 gssd_cred_verifier; GSS_CRED_ID_T cred_handle; }; typedef struct gss_inquire_cred_arg gss_inquire_cred_arg; struct gss_inquire_cred_res { OM_UINT32 minor_status; GSS_BUFFER_T name; GSS_OID name_type; OM_UINT32 lifetime; int cred_usage; GSS_OID_SET mechanisms; OM_UINT32 status; }; typedef struct gss_inquire_cred_res gss_inquire_cred_res; struct gss_inquire_cred_by_mech_arg { uid_t uid; OM_UINT32 gssd_cred_verifier; GSS_CRED_ID_T cred_handle; GSS_OID mech_type; }; typedef struct gss_inquire_cred_by_mech_arg gss_inquire_cred_by_mech_arg; struct gss_inquire_cred_by_mech_res { OM_UINT32 minor_status; OM_UINT32 status; }; typedef struct gss_inquire_cred_by_mech_res gss_inquire_cred_by_mech_res; struct gsscred_name_to_unix_cred_arg { uid_t uid; GSS_BUFFER_T pname; GSS_OID name_type; GSS_OID mech_type; }; typedef struct gsscred_name_to_unix_cred_arg gsscred_name_to_unix_cred_arg; struct gsscred_name_to_unix_cred_res { uid_t uid; gid_t gid; GSSCRED_GIDS gids; OM_UINT32 major; }; typedef struct gsscred_name_to_unix_cred_res gsscred_name_to_unix_cred_res; struct gsscred_expname_to_unix_cred_arg { uid_t uid; GSS_BUFFER_T expname; }; typedef struct gsscred_expname_to_unix_cred_arg gsscred_expname_to_unix_cred_arg; struct gsscred_expname_to_unix_cred_res { uid_t uid; gid_t gid; GSSCRED_GIDS gids; OM_UINT32 major; }; typedef struct gsscred_expname_to_unix_cred_res gsscred_expname_to_unix_cred_res; struct gss_get_group_info_arg { uid_t uid; uid_t puid; }; typedef struct gss_get_group_info_arg gss_get_group_info_arg; struct gss_get_group_info_res { gid_t gid; GSSCRED_GIDS gids; OM_UINT32 major; }; typedef struct gss_get_group_info_res gss_get_group_info_res; struct gss_get_kmod_arg { GSS_OID mech_oid; }; typedef struct gss_get_kmod_arg gss_get_kmod_arg; struct gss_get_kmod_res { bool_t module_follow; union { char *modname; } gss_get_kmod_res_u; }; typedef struct gss_get_kmod_res gss_get_kmod_res; #define GSSPROG 100234 #define GSSVERS 1 #if defined(__STDC__) || defined(__cplusplus) #define GSS_ACQUIRE_CRED 1 extern enum clnt_stat gss_acquire_cred_1(gss_acquire_cred_arg *, gss_acquire_cred_res *, CLIENT *); extern bool_t gss_acquire_cred_1_svc(gss_acquire_cred_arg *, gss_acquire_cred_res *, struct svc_req *); #define GSS_RELEASE_CRED 2 extern enum clnt_stat gss_release_cred_1(gss_release_cred_arg *, gss_release_cred_res *, CLIENT *); extern bool_t gss_release_cred_1_svc(gss_release_cred_arg *, gss_release_cred_res *, struct svc_req *); #define GSS_INIT_SEC_CONTEXT 3 extern enum clnt_stat gss_init_sec_context_1(gss_init_sec_context_arg *, gss_init_sec_context_res *, CLIENT *); extern bool_t gss_init_sec_context_1_svc(gss_init_sec_context_arg *, gss_init_sec_context_res *, struct svc_req *); #define GSS_ACCEPT_SEC_CONTEXT 4 extern enum clnt_stat gss_accept_sec_context_1(gss_accept_sec_context_arg *, gss_accept_sec_context_res *, CLIENT *); extern bool_t gss_accept_sec_context_1_svc(gss_accept_sec_context_arg *, gss_accept_sec_context_res *, struct svc_req *); #define GSS_PROCESS_CONTEXT_TOKEN 5 extern enum clnt_stat gss_process_context_token_1(gss_process_context_token_arg *, gss_process_context_token_res *, CLIENT *); extern bool_t gss_process_context_token_1_svc(gss_process_context_token_arg *, gss_process_context_token_res *, struct svc_req *); #define GSS_DELETE_SEC_CONTEXT 6 extern enum clnt_stat gss_delete_sec_context_1(gss_delete_sec_context_arg *, gss_delete_sec_context_res *, CLIENT *); extern bool_t gss_delete_sec_context_1_svc(gss_delete_sec_context_arg *, gss_delete_sec_context_res *, struct svc_req *); #define GSS_CONTEXT_TIME 7 extern enum clnt_stat gss_context_time_1(gss_context_time_arg *, gss_context_time_res *, CLIENT *); extern bool_t gss_context_time_1_svc(gss_context_time_arg *, gss_context_time_res *, struct svc_req *); #define GSS_SIGN 8 extern enum clnt_stat gss_sign_1(gss_sign_arg *, gss_sign_res *, CLIENT *); extern bool_t gss_sign_1_svc(gss_sign_arg *, gss_sign_res *, struct svc_req *); #define GSS_VERIFY 9 extern enum clnt_stat gss_verify_1(gss_verify_arg *, gss_verify_res *, CLIENT *); extern bool_t gss_verify_1_svc(gss_verify_arg *, gss_verify_res *, struct svc_req *); #define GSS_DISPLAY_STATUS 10 extern enum clnt_stat gss_display_status_1(gss_display_status_arg *, gss_display_status_res *, CLIENT *); extern bool_t gss_display_status_1_svc(gss_display_status_arg *, gss_display_status_res *, struct svc_req *); #define GSS_INDICATE_MECHS 11 extern enum clnt_stat gss_indicate_mechs_1(void *, gss_indicate_mechs_res *, CLIENT *); extern bool_t gss_indicate_mechs_1_svc(void *, gss_indicate_mechs_res *, struct svc_req *); #define GSS_INQUIRE_CRED 12 extern enum clnt_stat gss_inquire_cred_1(gss_inquire_cred_arg *, gss_inquire_cred_res *, CLIENT *); extern bool_t gss_inquire_cred_1_svc(gss_inquire_cred_arg *, gss_inquire_cred_res *, struct svc_req *); #define GSS_SEAL 13 extern enum clnt_stat gss_seal_1(gss_seal_arg *, gss_seal_res *, CLIENT *); extern bool_t gss_seal_1_svc(gss_seal_arg *, gss_seal_res *, struct svc_req *); #define GSS_UNSEAL 14 extern enum clnt_stat gss_unseal_1(gss_unseal_arg *, gss_unseal_res *, CLIENT *); extern bool_t gss_unseal_1_svc(gss_unseal_arg *, gss_unseal_res *, struct svc_req *); #define GSSCRED_EXPNAME_TO_UNIX_CRED 15 extern enum clnt_stat gsscred_expname_to_unix_cred_1(gsscred_expname_to_unix_cred_arg *, gsscred_expname_to_unix_cred_res *, CLIENT *); extern bool_t gsscred_expname_to_unix_cred_1_svc(gsscred_expname_to_unix_cred_arg *, gsscred_expname_to_unix_cred_res *, struct svc_req *); #define GSSCRED_NAME_TO_UNIX_CRED 16 extern enum clnt_stat gsscred_name_to_unix_cred_1(gsscred_name_to_unix_cred_arg *, gsscred_name_to_unix_cred_res *, CLIENT *); extern bool_t gsscred_name_to_unix_cred_1_svc(gsscred_name_to_unix_cred_arg *, gsscred_name_to_unix_cred_res *, struct svc_req *); #define GSS_GET_GROUP_INFO 17 extern enum clnt_stat gss_get_group_info_1(gss_get_group_info_arg *, gss_get_group_info_res *, CLIENT *); extern bool_t gss_get_group_info_1_svc(gss_get_group_info_arg *, gss_get_group_info_res *, struct svc_req *); #define GSS_GET_KMOD 18 extern enum clnt_stat gss_get_kmod_1(gss_get_kmod_arg *, gss_get_kmod_res *, CLIENT *); extern bool_t gss_get_kmod_1_svc(gss_get_kmod_arg *, gss_get_kmod_res *, struct svc_req *); #define GSS_EXPORT_SEC_CONTEXT 19 extern enum clnt_stat gss_export_sec_context_1(gss_export_sec_context_arg *, gss_export_sec_context_res *, CLIENT *); extern bool_t gss_export_sec_context_1_svc(gss_export_sec_context_arg *, gss_export_sec_context_res *, struct svc_req *); #define GSS_IMPORT_SEC_CONTEXT 20 extern enum clnt_stat gss_import_sec_context_1(gss_import_sec_context_arg *, gss_import_sec_context_res *, CLIENT *); extern bool_t gss_import_sec_context_1_svc(gss_import_sec_context_arg *, gss_import_sec_context_res *, struct svc_req *); #define GSS_ADD_CRED 21 extern enum clnt_stat gss_add_cred_1(gss_add_cred_arg *, gss_add_cred_res *, CLIENT *); extern bool_t gss_add_cred_1_svc(gss_add_cred_arg *, gss_add_cred_res *, struct svc_req *); #define GSS_INQUIRE_CRED_BY_MECH 22 extern enum clnt_stat gss_inquire_cred_by_mech_1(gss_inquire_cred_by_mech_arg *, gss_inquire_cred_by_mech_res *, CLIENT *); extern bool_t gss_inquire_cred_by_mech_1_svc(gss_inquire_cred_by_mech_arg *, gss_inquire_cred_by_mech_res *, struct svc_req *); extern int gssprog_1_freeresult(SVCXPRT *, xdrproc_t, caddr_t); #else /* K&R C */ #define GSS_ACQUIRE_CRED 1 extern enum clnt_stat gss_acquire_cred_1(); extern bool_t gss_acquire_cred_1_svc(); #define GSS_RELEASE_CRED 2 extern enum clnt_stat gss_release_cred_1(); extern bool_t gss_release_cred_1_svc(); #define GSS_INIT_SEC_CONTEXT 3 extern enum clnt_stat gss_init_sec_context_1(); extern bool_t gss_init_sec_context_1_svc(); #define GSS_ACCEPT_SEC_CONTEXT 4 extern enum clnt_stat gss_accept_sec_context_1(); extern bool_t gss_accept_sec_context_1_svc(); #define GSS_PROCESS_CONTEXT_TOKEN 5 extern enum clnt_stat gss_process_context_token_1(); extern bool_t gss_process_context_token_1_svc(); #define GSS_DELETE_SEC_CONTEXT 6 extern enum clnt_stat gss_delete_sec_context_1(); extern bool_t gss_delete_sec_context_1_svc(); #define GSS_CONTEXT_TIME 7 extern enum clnt_stat gss_context_time_1(); extern bool_t gss_context_time_1_svc(); #define GSS_SIGN 8 extern enum clnt_stat gss_sign_1(); extern bool_t gss_sign_1_svc(); #define GSS_VERIFY 9 extern enum clnt_stat gss_verify_1(); extern bool_t gss_verify_1_svc(); #define GSS_DISPLAY_STATUS 10 extern enum clnt_stat gss_display_status_1(); extern bool_t gss_display_status_1_svc(); #define GSS_INDICATE_MECHS 11 extern enum clnt_stat gss_indicate_mechs_1(); extern bool_t gss_indicate_mechs_1_svc(); #define GSS_INQUIRE_CRED 12 extern enum clnt_stat gss_inquire_cred_1(); extern bool_t gss_inquire_cred_1_svc(); #define GSS_SEAL 13 extern enum clnt_stat gss_seal_1(); extern bool_t gss_seal_1_svc(); #define GSS_UNSEAL 14 extern enum clnt_stat gss_unseal_1(); extern bool_t gss_unseal_1_svc(); #define GSSCRED_EXPNAME_TO_UNIX_CRED 15 extern enum clnt_stat gsscred_expname_to_unix_cred_1(); extern bool_t gsscred_expname_to_unix_cred_1_svc(); #define GSSCRED_NAME_TO_UNIX_CRED 16 extern enum clnt_stat gsscred_name_to_unix_cred_1(); extern bool_t gsscred_name_to_unix_cred_1_svc(); #define GSS_GET_GROUP_INFO 17 extern enum clnt_stat gss_get_group_info_1(); extern bool_t gss_get_group_info_1_svc(); #define GSS_GET_KMOD 18 extern enum clnt_stat gss_get_kmod_1(); extern bool_t gss_get_kmod_1_svc(); #define GSS_EXPORT_SEC_CONTEXT 19 extern enum clnt_stat gss_export_sec_context_1(); extern bool_t gss_export_sec_context_1_svc(); #define GSS_IMPORT_SEC_CONTEXT 20 extern enum clnt_stat gss_import_sec_context_1(); extern bool_t gss_import_sec_context_1_svc(); #define GSS_ADD_CRED 21 extern enum clnt_stat gss_add_cred_1(); extern bool_t gss_add_cred_1_svc(); #define GSS_INQUIRE_CRED_BY_MECH 22 extern enum clnt_stat gss_inquire_cred_by_mech_1(); extern bool_t gss_inquire_cred_by_mech_1_svc(); extern int gssprog_1_freeresult(); #endif /* K&R C */ /* the xdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern bool_t xdr_OM_UINT32(XDR *, OM_UINT32*); extern bool_t xdr_GSS_CTX_ID_T(XDR *, GSS_CTX_ID_T*); extern bool_t xdr_GSS_CRED_ID_T(XDR *, GSS_CRED_ID_T*); extern bool_t xdr_GSS_OID(XDR *, GSS_OID*); extern bool_t xdr_GSS_BUFFER_T(XDR *, GSS_BUFFER_T*); extern bool_t xdr_GSSCRED_GIDS(XDR *, GSSCRED_GIDS*); extern bool_t xdr_GSS_OID_SET(XDR *, GSS_OID_SET*); extern bool_t xdr_GSS_CHANNEL_BINDINGS_STRUCT(XDR *, GSS_CHANNEL_BINDINGS_STRUCT*); extern bool_t xdr_GSS_CHANNEL_BINDINGS(XDR *, GSS_CHANNEL_BINDINGS*); extern bool_t xdr_gss_acquire_cred_arg(XDR *, gss_acquire_cred_arg*); extern bool_t xdr_gss_acquire_cred_res(XDR *, gss_acquire_cred_res*); extern bool_t xdr_gss_add_cred_arg(XDR *, gss_add_cred_arg*); extern bool_t xdr_gss_add_cred_res(XDR *, gss_add_cred_res*); extern bool_t xdr_gss_release_cred_arg(XDR *, gss_release_cred_arg*); extern bool_t xdr_gss_release_cred_res(XDR *, gss_release_cred_res*); extern bool_t xdr_gss_init_sec_context_arg(XDR *, gss_init_sec_context_arg*); extern bool_t xdr_gss_init_sec_context_res(XDR *, gss_init_sec_context_res*); extern bool_t xdr_gss_accept_sec_context_arg(XDR *, gss_accept_sec_context_arg*); extern bool_t xdr_gss_accept_sec_context_res(XDR *, gss_accept_sec_context_res*); extern bool_t xdr_gss_process_context_token_arg(XDR *, gss_process_context_token_arg*); extern bool_t xdr_gss_process_context_token_res(XDR *, gss_process_context_token_res*); extern bool_t xdr_gss_delete_sec_context_arg(XDR *, gss_delete_sec_context_arg*); extern bool_t xdr_gss_delete_sec_context_res(XDR *, gss_delete_sec_context_res*); extern bool_t xdr_gss_export_sec_context_arg(XDR *, gss_export_sec_context_arg*); extern bool_t xdr_gss_export_sec_context_res(XDR *, gss_export_sec_context_res*); extern bool_t xdr_gss_import_sec_context_arg(XDR *, gss_import_sec_context_arg*); extern bool_t xdr_gss_import_sec_context_res(XDR *, gss_import_sec_context_res*); extern bool_t xdr_gss_context_time_arg(XDR *, gss_context_time_arg*); extern bool_t xdr_gss_context_time_res(XDR *, gss_context_time_res*); extern bool_t xdr_gss_sign_arg(XDR *, gss_sign_arg*); extern bool_t xdr_gss_sign_res(XDR *, gss_sign_res*); extern bool_t xdr_gss_verify_arg(XDR *, gss_verify_arg*); extern bool_t xdr_gss_verify_res(XDR *, gss_verify_res*); extern bool_t xdr_gss_seal_arg(XDR *, gss_seal_arg*); extern bool_t xdr_gss_seal_res(XDR *, gss_seal_res*); extern bool_t xdr_gss_unseal_arg(XDR *, gss_unseal_arg*); extern bool_t xdr_gss_unseal_res(XDR *, gss_unseal_res*); extern bool_t xdr_gss_display_status_arg(XDR *, gss_display_status_arg*); extern bool_t xdr_gss_display_status_res(XDR *, gss_display_status_res*); extern bool_t xdr_gss_indicate_mechs_res(XDR *, gss_indicate_mechs_res*); extern bool_t xdr_gss_inquire_cred_arg(XDR *, gss_inquire_cred_arg*); extern bool_t xdr_gss_inquire_cred_res(XDR *, gss_inquire_cred_res*); extern bool_t xdr_gss_inquire_cred_by_mech_arg(XDR *, gss_inquire_cred_by_mech_arg*); extern bool_t xdr_gss_inquire_cred_by_mech_res(XDR *, gss_inquire_cred_by_mech_res*); extern bool_t xdr_gsscred_name_to_unix_cred_arg(XDR *, gsscred_name_to_unix_cred_arg*); extern bool_t xdr_gsscred_name_to_unix_cred_res(XDR *, gsscred_name_to_unix_cred_res*); extern bool_t xdr_gsscred_expname_to_unix_cred_arg(XDR *, gsscred_expname_to_unix_cred_arg*); extern bool_t xdr_gsscred_expname_to_unix_cred_res(XDR *, gsscred_expname_to_unix_cred_res*); extern bool_t xdr_gss_get_group_info_arg(XDR *, gss_get_group_info_arg*); extern bool_t xdr_gss_get_group_info_res(XDR *, gss_get_group_info_res*); extern bool_t xdr_gss_get_kmod_arg(XDR *, gss_get_kmod_arg*); extern bool_t xdr_gss_get_kmod_res(XDR *, gss_get_kmod_res*); #else /* K&R C */ extern bool_t xdr_OM_UINT32(); extern bool_t xdr_GSS_CTX_ID_T(); extern bool_t xdr_GSS_CRED_ID_T(); extern bool_t xdr_GSS_OID(); extern bool_t xdr_GSS_BUFFER_T(); extern bool_t xdr_GSSCRED_GIDS(); extern bool_t xdr_GSS_OID_SET(); extern bool_t xdr_GSS_CHANNEL_BINDINGS_STRUCT(); extern bool_t xdr_GSS_CHANNEL_BINDINGS(); extern bool_t xdr_gss_acquire_cred_arg(); extern bool_t xdr_gss_acquire_cred_res(); extern bool_t xdr_gss_add_cred_arg(); extern bool_t xdr_gss_add_cred_res(); extern bool_t xdr_gss_release_cred_arg(); extern bool_t xdr_gss_release_cred_res(); extern bool_t xdr_gss_init_sec_context_arg(); extern bool_t xdr_gss_init_sec_context_res(); extern bool_t xdr_gss_accept_sec_context_arg(); extern bool_t xdr_gss_accept_sec_context_res(); extern bool_t xdr_gss_process_context_token_arg(); extern bool_t xdr_gss_process_context_token_res(); extern bool_t xdr_gss_delete_sec_context_arg(); extern bool_t xdr_gss_delete_sec_context_res(); extern bool_t xdr_gss_export_sec_context_arg(); extern bool_t xdr_gss_export_sec_context_res(); extern bool_t xdr_gss_import_sec_context_arg(); extern bool_t xdr_gss_import_sec_context_res(); extern bool_t xdr_gss_context_time_arg(); extern bool_t xdr_gss_context_time_res(); extern bool_t xdr_gss_sign_arg(); extern bool_t xdr_gss_sign_res(); extern bool_t xdr_gss_verify_arg(); extern bool_t xdr_gss_verify_res(); extern bool_t xdr_gss_seal_arg(); extern bool_t xdr_gss_seal_res(); extern bool_t xdr_gss_unseal_arg(); extern bool_t xdr_gss_unseal_res(); extern bool_t xdr_gss_display_status_arg(); extern bool_t xdr_gss_display_status_res(); extern bool_t xdr_gss_indicate_mechs_res(); extern bool_t xdr_gss_inquire_cred_arg(); extern bool_t xdr_gss_inquire_cred_res(); extern bool_t xdr_gss_inquire_cred_by_mech_arg(); extern bool_t xdr_gss_inquire_cred_by_mech_res(); extern bool_t xdr_gsscred_name_to_unix_cred_arg(); extern bool_t xdr_gsscred_name_to_unix_cred_res(); extern bool_t xdr_gsscred_expname_to_unix_cred_arg(); extern bool_t xdr_gsscred_expname_to_unix_cred_res(); extern bool_t xdr_gss_get_group_info_arg(); extern bool_t xdr_gss_get_group_info_res(); extern bool_t xdr_gss_get_kmod_arg(); extern bool_t xdr_gss_get_kmod_res(); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_GSSD_H_RPCGEN */ /* * Please do not edit this file. * It was generated using rpcgen. */ #include "gssd_prot.h" #ifndef _KERNEL #include #endif /* !_KERNEL */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * RPC protocol information for gssd, the usermode daemon that * assists the kernel with gssapi. It is gssd that executes all * gssapi calls except for some such as gss_sign(), and * gss_verify(), which are executed in the kernel itself. * * File generated from gssd.x */ #define NO 0 #define YES 1 #define FOREVER 1 #include #include #include #ifndef _KERNEL #include #endif /* not _KERNEL */ #ifdef _KERNEL extern void killgssd_handle(CLIENT *); extern CLIENT *getgssd_handle(void); #endif /* _KERNEL */ bool_t xdr_OM_UINT32(xdrs, objp) XDR *xdrs; OM_UINT32 *objp; { rpc_inline_t *buf __unused; if (!xdr_u_int(xdrs, objp)) return (FALSE); return (TRUE); } bool_t xdr_GSS_CTX_ID_T(xdrs, objp) XDR *xdrs; GSS_CTX_ID_T *objp; { rpc_inline_t *buf __unused; if (!xdr_bytes(xdrs, (char **)&objp->GSS_CTX_ID_T_val, (u_int *) &objp->GSS_CTX_ID_T_len, ~0)) return (FALSE); return (TRUE); } bool_t xdr_GSS_CRED_ID_T(xdrs, objp) XDR *xdrs; GSS_CRED_ID_T *objp; { rpc_inline_t *buf __unused; if (!xdr_bytes(xdrs, (char **)&objp->GSS_CRED_ID_T_val, (u_int *) &objp->GSS_CRED_ID_T_len, ~0)) return (FALSE); return (TRUE); } bool_t xdr_GSS_OID(xdrs, objp) XDR *xdrs; GSS_OID *objp; { rpc_inline_t *buf __unused; if (!xdr_bytes(xdrs, (char **)&objp->GSS_OID_val, (u_int *) &objp->GSS_OID_len, ~0)) return (FALSE); return (TRUE); } bool_t xdr_GSS_BUFFER_T(xdrs, objp) XDR *xdrs; GSS_BUFFER_T *objp; { rpc_inline_t *buf __unused; if (!xdr_bytes(xdrs, (char **)&objp->GSS_BUFFER_T_val, (u_int *) &objp->GSS_BUFFER_T_len, ~0)) return (FALSE); return (TRUE); } bool_t xdr_GSSCRED_GIDS(xdrs, objp) XDR *xdrs; GSSCRED_GIDS *objp; { rpc_inline_t *buf __unused; if (!xdr_array(xdrs, (char **)&objp->GSSCRED_GIDS_val, (u_int *) &objp->GSSCRED_GIDS_len, ~0, sizeof (gid_t), (xdrproc_t)xdr_gid_t)) return (FALSE); return (TRUE); } bool_t xdr_GSS_OID_SET(xdrs, objp) XDR *xdrs; GSS_OID_SET *objp; { rpc_inline_t *buf __unused; if (!xdr_array(xdrs, (char **)&objp->GSS_OID_SET_val, (u_int *) &objp->GSS_OID_SET_len, ~0, sizeof (GSS_OID), (xdrproc_t)xdr_GSS_OID)) return (FALSE); return (TRUE); } bool_t xdr_GSS_CHANNEL_BINDINGS_STRUCT(xdrs, objp) XDR *xdrs; GSS_CHANNEL_BINDINGS_STRUCT *objp; { rpc_inline_t *buf __unused; if (!xdr_int(xdrs, &objp->present)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->initiator_addrtype)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->initiator_address)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->acceptor_addrtype)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->acceptor_address)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->application_data)) return (FALSE); return (TRUE); } bool_t xdr_GSS_CHANNEL_BINDINGS(xdrs, objp) XDR *xdrs; GSS_CHANNEL_BINDINGS *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_CHANNEL_BINDINGS_STRUCT(xdrs, objp)) return (FALSE); return (TRUE); } bool_t xdr_gss_acquire_cred_arg(xdrs, objp) XDR *xdrs; gss_acquire_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->desired_name)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->name_type)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_req)) return (FALSE); if (!xdr_GSS_OID_SET(xdrs, &objp->desired_mechs)) return (FALSE); if (!xdr_int(xdrs, &objp->cred_usage)) return (FALSE); return (TRUE); } bool_t xdr_gss_acquire_cred_res(xdrs, objp) XDR *xdrs; gss_acquire_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->output_cred_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_OID_SET(xdrs, &objp->actual_mechs)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_rec)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_add_cred_arg(xdrs, objp) XDR *xdrs; gss_add_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->input_cred_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->desired_name)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->name_type)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->desired_mech_type)) return (FALSE); if (!xdr_int(xdrs, &objp->cred_usage)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->initiator_time_req)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->acceptor_time_req)) return (FALSE); return (TRUE); } bool_t xdr_gss_add_cred_res(xdrs, objp) XDR *xdrs; gss_add_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_OID_SET(xdrs, &objp->actual_mechs)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->initiator_time_rec)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->acceptor_time_rec)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_release_cred_arg(xdrs, objp) XDR *xdrs; gss_release_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle)) return (FALSE); return (TRUE); } bool_t xdr_gss_release_cred_res(xdrs, objp) XDR *xdrs; gss_release_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_init_sec_context_arg(xdrs, objp) XDR *xdrs; gss_init_sec_context_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->claimant_cred_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->target_name)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->name_type)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->mech_type)) return (FALSE); if (!xdr_int(xdrs, &objp->req_flags)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_req)) return (FALSE); if (!xdr_GSS_CHANNEL_BINDINGS(xdrs, &objp->input_chan_bindings)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token)) return (FALSE); return (TRUE); } bool_t xdr_gss_init_sec_context_res(xdrs, objp) XDR *xdrs; gss_init_sec_context_res *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->actual_mech_type)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->ret_flags)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_rec)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_accept_sec_context_arg(xdrs, objp) XDR *xdrs; gss_accept_sec_context_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->verifier_cred_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token_buffer)) return (FALSE); if (!xdr_GSS_CHANNEL_BINDINGS(xdrs, &objp->input_chan_bindings)) return (FALSE); return (TRUE); } bool_t xdr_gss_accept_sec_context_res(xdrs, objp) XDR *xdrs; gss_accept_sec_context_res *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->src_name)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->mech_type)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->ret_flags)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_rec)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->delegated_cred_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_process_context_token_arg(xdrs, objp) XDR *xdrs; gss_process_context_token_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->token_buffer)) return (FALSE); return (TRUE); } bool_t xdr_gss_process_context_token_res(xdrs, objp) XDR *xdrs; gss_process_context_token_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_delete_sec_context_arg(xdrs, objp) XDR *xdrs; gss_delete_sec_context_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); return (TRUE); } bool_t xdr_gss_delete_sec_context_res(xdrs, objp) XDR *xdrs; gss_delete_sec_context_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_export_sec_context_arg(xdrs, objp) XDR *xdrs; gss_export_sec_context_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); return (TRUE); } bool_t xdr_gss_export_sec_context_res(xdrs, objp) XDR *xdrs; gss_export_sec_context_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_import_sec_context_arg(xdrs, objp) XDR *xdrs; gss_import_sec_context_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); return (TRUE); } bool_t xdr_gss_import_sec_context_res(xdrs, objp) XDR *xdrs; gss_import_sec_context_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_context_time_arg(xdrs, objp) XDR *xdrs; gss_context_time_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); return (TRUE); } bool_t xdr_gss_context_time_res(xdrs, objp) XDR *xdrs; gss_context_time_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->time_rec)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_sign_arg(xdrs, objp) XDR *xdrs; gss_sign_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_int(xdrs, &objp->qop_req)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->message_buffer)) return (FALSE); return (TRUE); } bool_t xdr_gss_sign_res(xdrs, objp) XDR *xdrs; gss_sign_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->msg_token)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_verify_arg(xdrs, objp) XDR *xdrs; gss_verify_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->message_buffer)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->token_buffer)) return (FALSE); return (TRUE); } bool_t xdr_gss_verify_res(xdrs, objp) XDR *xdrs; gss_verify_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_int(xdrs, &objp->qop_state)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_seal_arg(xdrs, objp) XDR *xdrs; gss_seal_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_int(xdrs, &objp->conf_req_flag)) return (FALSE); if (!xdr_int(xdrs, &objp->qop_req)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_message_buffer)) return (FALSE); return (TRUE); } bool_t xdr_gss_seal_res(xdrs, objp) XDR *xdrs; gss_seal_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_int(xdrs, &objp->conf_state)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_message_buffer)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_unseal_arg(xdrs, objp) XDR *xdrs; gss_unseal_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->gssd_context_verifier)) return (FALSE); if (!xdr_GSS_CTX_ID_T(xdrs, &objp->context_handle)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->input_message_buffer)) return (FALSE); return (TRUE); } bool_t xdr_gss_unseal_res(xdrs, objp) XDR *xdrs; gss_unseal_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->output_message_buffer)) return (FALSE); if (!xdr_int(xdrs, &objp->conf_state)) return (FALSE); if (!xdr_int(xdrs, &objp->qop_state)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_display_status_arg(xdrs, objp) XDR *xdrs; gss_display_status_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_int(xdrs, &objp->status_value)) return (FALSE); if (!xdr_int(xdrs, &objp->status_type)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->mech_type)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->message_context)) return (FALSE); return (TRUE); } bool_t xdr_gss_display_status_res(xdrs, objp) XDR *xdrs; gss_display_status_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_int(xdrs, &objp->message_context)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->status_string)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } /* gss_indicate_mechs_arg is void. This appears in the rpc call def */ bool_t xdr_gss_indicate_mechs_res(xdrs, objp) XDR *xdrs; gss_indicate_mechs_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_OID_SET(xdrs, &objp->mech_set)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_inquire_cred_arg(xdrs, objp) XDR *xdrs; gss_inquire_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle)) return (FALSE); return (TRUE); } bool_t xdr_gss_inquire_cred_res(xdrs, objp) XDR *xdrs; gss_inquire_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->name)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->name_type)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->lifetime)) return (FALSE); if (!xdr_int(xdrs, &objp->cred_usage)) return (FALSE); if (!xdr_GSS_OID_SET(xdrs, &objp->mechanisms)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gss_inquire_cred_by_mech_arg(xdrs, objp) XDR *xdrs; gss_inquire_cred_by_mech_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->gssd_cred_verifier)) return (FALSE); if (!xdr_GSS_CRED_ID_T(xdrs, &objp->cred_handle)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->mech_type)) return (FALSE); return (TRUE); } bool_t xdr_gss_inquire_cred_by_mech_res(xdrs, objp) XDR *xdrs; gss_inquire_cred_by_mech_res *objp; { rpc_inline_t *buf __unused; if (!xdr_OM_UINT32(xdrs, &objp->minor_status)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->status)) return (FALSE); return (TRUE); } bool_t xdr_gsscred_name_to_unix_cred_arg(xdrs, objp) XDR *xdrs; gsscred_name_to_unix_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->pname)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->name_type)) return (FALSE); if (!xdr_GSS_OID(xdrs, &objp->mech_type)) return (FALSE); return (TRUE); } bool_t xdr_gsscred_name_to_unix_cred_res(xdrs, objp) XDR *xdrs; gsscred_name_to_unix_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_gid_t(xdrs, &objp->gid)) return (FALSE); if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->major)) return (FALSE); return (TRUE); } bool_t xdr_gsscred_expname_to_unix_cred_arg(xdrs, objp) XDR *xdrs; gsscred_expname_to_unix_cred_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_GSS_BUFFER_T(xdrs, &objp->expname)) return (FALSE); return (TRUE); } bool_t xdr_gsscred_expname_to_unix_cred_res(xdrs, objp) XDR *xdrs; gsscred_expname_to_unix_cred_res *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_gid_t(xdrs, &objp->gid)) return (FALSE); if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->major)) return (FALSE); return (TRUE); } bool_t xdr_gss_get_group_info_arg(xdrs, objp) XDR *xdrs; gss_get_group_info_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_uid_t(xdrs, &objp->uid)) return (FALSE); if (!xdr_uid_t(xdrs, &objp->puid)) return (FALSE); return (TRUE); } bool_t xdr_gss_get_group_info_res(xdrs, objp) XDR *xdrs; gss_get_group_info_res *objp; { rpc_inline_t *buf __unused; if (!xdr_gid_t(xdrs, &objp->gid)) return (FALSE); if (!xdr_GSSCRED_GIDS(xdrs, &objp->gids)) return (FALSE); if (!xdr_OM_UINT32(xdrs, &objp->major)) return (FALSE); return (TRUE); } bool_t xdr_gss_get_kmod_arg(xdrs, objp) XDR *xdrs; gss_get_kmod_arg *objp; { rpc_inline_t *buf __unused; if (!xdr_GSS_OID(xdrs, &objp->mech_oid)) return (FALSE); return (TRUE); } bool_t xdr_gss_get_kmod_res(xdrs, objp) XDR *xdrs; gss_get_kmod_res *objp; { rpc_inline_t *buf __unused; if (!xdr_bool(xdrs, &objp->module_follow)) return (FALSE); switch (objp->module_follow) { case TRUE: if (!xdr_string(xdrs, &objp->gss_get_kmod_res_u.modname, ~0)) return (FALSE); break; case FALSE: break; default: return (FALSE); } return (TRUE); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. */ #include #include #include #include static struct modlmisc modlmisc = { &mod_miscops, "in-kernel GSSAPI" }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modlmisc, NULL }; int _init() { int retval; mutex_init(&gssrpcb_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&__kgss_mech_lock, NULL, MUTEX_DEFAULT, NULL); zone_key_create(&gss_zone_key, gss_zone_init, NULL, gss_zone_fini); if ((retval = mod_install(&modlinkage)) != 0) { mutex_destroy(&__kgss_mech_lock); mutex_destroy(&gssrpcb_lock); } return (retval); } int _fini() { return (EBUSY); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _GSSAPIP_DUMMY_H #define _GSSAPIP_DUMMY_H #ifdef __cplusplus extern "C" { #endif #include #define SEC_CONTEXT_TOKEN 1 #define DUMMY_SIZE_OF_INT 4 typedef void * dummy_token_t; /* dummy name structure for internal representation. */ typedef struct { gss_OID type; gss_buffer_t buffer; } dummy_name_desc, *dummy_name_t; /* Structure for context handle */ typedef struct { OM_uint32 last_stat; int token_number; int established; } dummy_gss_ctx_id_rec, *dummy_gss_ctx_id_t; /* Dummy oid structure */ static const gss_OID_desc dummy_oids[] = { {10, "\053\006\001\004\001\052\002\032\001\002"}, }; const gss_OID_desc * const gss_mech_dummy = dummy_oids+0; static const gss_OID_set_desc dummy_oidsets[] = { {1, (gss_OID) dummy_oids+0}, }; const gss_OID_set_desc * const gss_mech_set_dummy = dummy_oidsets+0; #define TWRITE_STR(ptr, str, len) \ (void) memcpy((ptr), (char *) (str), (len)); \ (ptr) += (len); #ifndef _KERNEL #ifdef DEBUG_ON #define dprintf(a) printf(a) #define dprintf1(a, b) printf(a, b) #else #define dprintf(a) #define dprintf1(a, b) #define DUMMY_STATIC #endif /* DEBUG_ON */ #else /* _KERNEL */ #if defined(DEBUG) && !defined(DUMMY_MECH_DEBUG) #define DUMMY_MECH_DEBUG #endif #ifdef DUMMY_MECH_DEBUG #define DUMMY_MECH_LOG(A, B, C) \ ((void)((dummy_mech_log & (A)) && (printf((B), (C)), TRUE))) #define DUMMY_MECH_LOG0(A, B) \ ((void)((dummy_mech_log & (A)) && (printf(B), TRUE))) #else #define DUMMY_MECH_LOG(A, B, C) #define DUMMY_MECH_LOG0(A, B) #endif #define dprintf(a) DUMMY_MECH_LOG0(8, a) #define dprintf1(a, b) DUMMY_MECH_LOG(8, a, b) #define DUMMY_STATIC static #endif /* _KERNEL */ /* * declarations of internal name mechanism functions */ OM_uint32 dummy_gss_acquire_cred ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_name_t, /* desired_name */ OM_uint32, /* time_req */ gss_OID_set, /* desired_mechs */ gss_cred_usage_t, /* cred_usage */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 * /* time_rec */ /* */); OM_uint32 dummy_gss_release_cred ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_cred_id_t * /* cred_handle */ /* */); OM_uint32 dummy_gss_init_sec_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_cred_id_t, /* claimant_cred_handle */ gss_ctx_id_t *, /* context_handle */ gss_name_t, /* target_name */ gss_OID, /* mech_type */ OM_uint32, /* req_flags */ OM_uint32, /* time_req */ gss_channel_bindings_t, /* input_chan_bindings */ gss_buffer_t, /* input_token */ gss_OID *, /* actual_mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 * /* time_rec */ /* */); OM_uint32 dummy_gss_accept_sec_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_cred_id_t, /* verifier_cred_handle */ gss_buffer_t, /* input_token_buffer */ gss_channel_bindings_t, /* input_chan_bindings */ gss_name_t *, /* src_name */ gss_OID *, /* mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 *, /* time_rec */ gss_cred_id_t * /* delegated_cred_handle */ /* */); OM_uint32 dummy_gss_process_context_token ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t /* token_buffer */ /* */); DUMMY_STATIC OM_uint32 dummy_gss_delete_sec_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* output_token */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); OM_uint32 dummy_gss_context_time ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ OM_uint32 * /* time_rec */ /* */); DUMMY_STATIC OM_uint32 dummy_gss_sign ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); DUMMY_STATIC OM_uint32 dummy_gss_verify ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* token_buffer */ int * /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); DUMMY_STATIC OM_uint32 dummy_gss_seal ( void *, /* dummy 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 */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); DUMMY_STATIC OM_uint32 dummy_gss_unseal ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ int * /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); OM_uint32 dummy_gss_display_status ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ OM_uint32, /* status_value */ int, /* status_type */ gss_OID, /* mech_type */ OM_uint32 *, /* message_context */ gss_buffer_t /* status_string */ /* */); OM_uint32 dummy_gss_indicate_mechs ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_OID_set * /* mech_set */ /* */); OM_uint32 dummy_gss_compare_name ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_name_t, /* name1 */ gss_name_t, /* name2 */ int * /* name_equal */ /* */); OM_uint32 dummy_gss_display_name ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_name_t, /* input_name */ gss_buffer_t, /* output_name_buffer */ gss_OID * /* output_name_type */ /* */); OM_uint32 dummy_gss_import_name ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_buffer_t, /* input_name_buffer */ gss_OID, /* input_name_type */ gss_name_t * /* output_name */ /* */); OM_uint32 dummy_gss_release_name ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_name_t * /* input_name */ /* */); OM_uint32 dummy_gss_inquire_cred ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_cred_id_t, /* cred_handle */ gss_name_t *, /* name */ OM_uint32 *, /* lifetime */ gss_cred_usage_t *, /* cred_usage */ gss_OID_set * /* mechanisms */ /* */); OM_uint32 dummy_gss_inquire_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_name_t *, /* initiator_name */ gss_name_t *, /* acceptor_name */ OM_uint32 *, /* lifetime_rec */ gss_OID *, /* mech_type */ OM_uint32 *, /* ret_flags */ int *, /* locally_initiated */ int * /* open */ /* */); /* New V2 entry points */ OM_uint32 dummy_gss_get_mic ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_qop_t, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ /* */); OM_uint32 dummy_gss_verify_mic ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* message_token */ gss_qop_t * /* qop_state */ /* */); OM_uint32 dummy_gss_wrap ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t /* output_message_buffer */ /* */); OM_uint32 dummy_gss_unwrap ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ gss_qop_t * /* qop_state */ /* */); OM_uint32 dummy_gss_wrap_size_limit ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ OM_uint32, /* req_output_size */ OM_uint32 * /* max_input_size */ /* */); OM_uint32 dummy_gss_add_cred ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_cred_id_t, /* input_cred_handle */ gss_name_t, /* desired_name */ gss_OID, /* desired_mech */ gss_cred_usage_t, /* cred_usage */ OM_uint32, /* initiator_time_req */ OM_uint32, /* acceptor_time_req */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 *, /* initiator_time_rec */ OM_uint32 * /* acceptor_time_rec */ /* */); OM_uint32 dummy_gss_inquire_cred_by_mech ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_cred_id_t, /* cred_handle */ gss_OID, /* mech_type */ gss_name_t *, /* name */ OM_uint32 *, /* initiator_lifetime */ OM_uint32 *, /* acceptor_lifetime */ gss_cred_usage_t * /* cred_usage */ /* */); OM_uint32 dummy_gss_export_sec_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* interprocess_token */ /* */); OM_uint32 dummy_gss_import_sec_context ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_buffer_t, /* interprocess_token */ gss_ctx_id_t * /* context_handle */ /* */); #if 0 OM_uint32 dummy_gss_release_oid ( OM_uint32 *, /* minor_status */ gss_OID * /* oid */ /* */); #endif OM_uint32 dummy_gss_internal_release_oid ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_OID * /* oid */ /* */); OM_uint32 dummy_gss_inquire_names_for_mech ( void *, /* dummy context */ OM_uint32 *, /* minor_status */ gss_OID, /* mechanism */ gss_OID_set * /* name_types */ /* */); OM_uint32 dummy_pname_to_uid ( void *, /* dummy context */ OM_uint32 *, /* minor status */ const gss_name_t, /* pname */ uid_t * /* uidOut */ /* */); #ifdef __cplusplus } #endif #endif /* _GSSAPIP_DUMMY_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * This file was derived from the MIT 1.0 source release. */ #ifndef _GSSAPI_ERR_GENERIC_H #define _GSSAPI_ERR_GENERIC_H #ifdef __cplusplus extern "C" { #endif /* * gssapi_err_generic.h: * This file is automatically generated; please do not edit it. */ #define G_BAD_SERVICE_NAME (-2045022976L) #define G_BAD_STRING_UID (-2045022975L) #define G_NOUSER (-2045022974L) #define G_VALIDATE_FAILED (-2045022973L) #define G_BUFFER_ALLOC (-2045022972L) #define G_BAD_MSG_CTX (-2045022971L) #define G_WRONG_SIZE (-2045022970L) #define G_BAD_USAGE (-2045022969L) #define G_UNKNOWN_QOP (-2045022968L) #define G_NO_HOSTNAME (-2045022967L) #define G_BAD_HOSTNAME (-2045022966L) #define G_WRONG_MECH (-2045022965L) #define G_BAD_TOK_HEADER (-2045022964L) #define G_BAD_DIRECTION (-2045022963L) #define G_TOK_TRUNC (-2045022962L) #define G_REFLECT (-2045022961L) #define G_WRONG_TOKID (-2045022960L) #define G_CRED_USAGE_MISMATCH (-2045022959L) #define G_STORE_ACCEPTOR_CRED_NOSUPP (-2045022958L) #define G_STORE_NON_DEFAULT_CRED_NOSUPP (-2045022957L) #define ERROR_TABLE_BASE_ggss (-2045022976L) /* for compatibility with older versions... */ #define ggss_err_base ERROR_TABLE_BASE_ggss #ifdef __cplusplus } #endif #endif /* _GSSAPI_ERR_GENERIC_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * This header contains the private mechglue definitions. * */ #ifndef _GSS_MECHGLUEP_H #define _GSS_MECHGLUEP_H #if 0 /* SUNW15resync - disable for sake of non-krb5 mechs */ #include "autoconf.h" #endif /* SUNW15resync */ #ifndef GSS_DLLIMP #define GSS_DLLIMP #endif #include /* SUNW15resync - mechglue.h in mit 1.5 */ #if 0 /* Solaris Kerberos */ #include "gssapiP_generic.h" #endif #ifdef _KERNEL #include #endif #ifndef g_OID_copy /* SUNW15resync */ #define g_OID_copy(o1, o2) \ do { \ memcpy((o1)->elements, (o2)->elements, (o2)->length); \ (o1)->length = (o2)->length; \ } while (0) #endif #define GSS_EMPTY_BUFFER(buf) ((buf) == NULL ||\ (buf)->value == NULL || (buf)->length == 0) /* * Array of context IDs typed by mechanism OID */ typedef struct gss_union_ctx_id_t { gss_OID mech_type; gss_ctx_id_t internal_ctx_id; } gss_union_ctx_id_desc, *gss_union_ctx_id_t; /* * Generic GSSAPI names. A name can either be a generic name, or a * mechanism specific name.... */ typedef struct gss_name_struct { struct gss_name_struct *loopback; gss_OID name_type; gss_buffer_t external_name; /* * These last two fields are only filled in for mechanism * names. */ gss_OID mech_type; gss_name_t mech_name; } gss_union_name_desc, *gss_union_name_t; /* * Structure for holding list of mechanism-specific name types */ typedef struct gss_mech_spec_name_t { gss_OID name_type; gss_OID mech; struct gss_mech_spec_name_t *next, *prev; } gss_mech_spec_name_desc, *gss_mech_spec_name; /* * Credential auxiliary info, used in the credential structure */ typedef struct gss_union_cred_auxinfo { gss_buffer_desc name; gss_OID name_type; OM_uint32 creation_time; OM_uint32 time_rec; int cred_usage; } gss_union_cred_auxinfo; /* * Set of Credentials typed on mechanism OID */ typedef struct gss_union_cred_t { int count; gss_OID mechs_array; gss_cred_id_t *cred_array; gss_union_cred_auxinfo auxinfo; } gss_union_cred_desc, *gss_union_cred_t; /* Solaris Kerberos */ typedef OM_uint32 (*gss_acquire_cred_with_password_sfct)( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* desired_name */ const gss_buffer_t, /* password */ OM_uint32, /* time_req */ const gss_OID_set, /* desired_mechs */ int, /* cred_usage */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 * /* time_rec */ /* */); /* * Rudimentary pointer validation macro to check whether the * "loopback" field of an opaque struct points back to itself. This * field also catches some programming errors where an opaque pointer * is passed to a function expecting the address of the opaque * pointer. */ #if 0 /* Solaris Kerberos - revisit for full 1.7/next resync */ #define GSSINT_CHK_LOOP(p) (!((p) != NULL && (p)->loopback == (p))) #else #define GSSINT_CHK_LOOP(p) ((p) == NULL) #endif /********************************************************/ /* The Mechanism Dispatch Table -- a mechanism needs to */ /* define one of these and provide a function to return */ /* it to initialize the GSSAPI library */ /* * This is the definition of the mechs_array struct, which is used to * define the mechs array table. This table is used to indirectly * access mechanism specific versions of the gssapi routines through * the routines in the glue module (gssd_mech_glue.c) * * This contants all of the functions defined in gssapi.h except for * gss_release_buffer() and gss_release_oid_set(), which I am * assuming, for now, to be equal across mechanisms. */ typedef struct gss_config { #if 0 /* Solaris Kerberos */ OM_uint32 priority; char * mechNameStr; #endif gss_OID_desc mech_type; void * context; #ifdef _KERNEL struct gss_config *next; bool_t uses_kmod; #endif #ifndef _KERNEL OM_uint32 (*gss_acquire_cred) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* desired_name */ OM_uint32, /* time_req */ const gss_OID_set, /* desired_mechs */ int, /* cred_usage */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 * /* time_rec */ /* */); OM_uint32 (*gss_release_cred) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_cred_id_t * /* cred_handle */ /* */); OM_uint32 (*gss_init_sec_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* claimant_cred_handle */ gss_ctx_id_t *, /* context_handle */ const gss_name_t, /* target_name */ const gss_OID, /* mech_type */ OM_uint32, /* req_flags */ OM_uint32, /* time_req */ const gss_channel_bindings_t, /* input_chan_bindings */ const gss_buffer_t, /* input_token */ gss_OID*, /* actual_mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 * /* time_rec */ /* */); OM_uint32 (*gss_accept_sec_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ const gss_cred_id_t, /* verifier_cred_handle */ const gss_buffer_t, /* input_token_buffer */ const gss_channel_bindings_t, /* input_chan_bindings */ gss_name_t *, /* src_name */ gss_OID*, /* mech_type */ gss_buffer_t, /* output_token */ OM_uint32 *, /* ret_flags */ OM_uint32 *, /* time_rec */ gss_cred_id_t * /* delegated_cred_handle */ /* */); #endif /* ! _KERNEL */ /* * Note: there are two gss_unseal's in here. Make any changes to both. */ OM_uint32 (*gss_unseal) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ int * /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); #ifndef _KERNEL OM_uint32 (*gss_process_context_token) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t /* token_buffer */ /* */); #endif /* ! _KERNEL */ OM_uint32 (*gss_delete_sec_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* output_token */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); #ifndef _KERNEL OM_uint32 (*gss_context_time) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ OM_uint32 * /* time_rec */ /* */); OM_uint32 (*gss_display_status) ( void *, /* context */ OM_uint32 *, /* minor_status */ OM_uint32, /* status_value */ int, /* status_type */ const gss_OID, /* mech_type */ OM_uint32 *, /* message_context */ gss_buffer_t /* status_string */ /* */); OM_uint32 (*gss_indicate_mechs) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_OID_set * /* mech_set */ /* */); OM_uint32 (*gss_compare_name) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* name1 */ const gss_name_t, /* name2 */ int * /* name_equal */ /* */); OM_uint32 (*gss_display_name) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_buffer_t, /* output_name_buffer */ gss_OID* /* output_name_type */ /* */); OM_uint32 (*gss_import_name) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_buffer_t, /* input_name_buffer */ const gss_OID, /* input_name_type */ gss_name_t * /* output_name */ /* */); OM_uint32 (*gss_release_name) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_name_t * /* input_name */ /* */); OM_uint32 (*gss_inquire_cred) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* cred_handle */ gss_name_t *, /* name */ OM_uint32 *, /* lifetime */ int *, /* cred_usage */ gss_OID_set * /* mechanisms */ /* */); OM_uint32 (*gss_add_cred) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred_handle */ const gss_name_t, /* desired_name */ const gss_OID, /* desired_mech */ gss_cred_usage_t, /* cred_usage */ OM_uint32, /* initiator_time_req */ OM_uint32, /* acceptor_time_req */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 *, /* initiator_time_rec */ OM_uint32 * /* acceptor_time_rec */ /* */); #endif /* ! _KERNEL */ /* * Note: there are two gss_seal's in here. Make any changes to both. */ OM_uint32 (*gss_seal) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ int, /* qop_req */ const gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t /* output_message_buffer */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); #ifndef _KERNEL OM_uint32 (*gss_export_sec_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* interprocess_token */ /* */); #endif /* ! _KERNEL */ OM_uint32 (*gss_import_sec_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_buffer_t, /* interprocess_token */ gss_ctx_id_t * /* context_handle */ /* */); #ifndef _KERNEL OM_uint32 (*gss_inquire_cred_by_mech) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* cred_handle */ const gss_OID, /* mech_type */ gss_name_t *, /* name */ OM_uint32 *, /* initiator_lifetime */ OM_uint32 *, /* acceptor_lifetime */ gss_cred_usage_t * /* cred_usage */ /* */); OM_uint32 (*gss_inquire_names_for_mech) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_OID, /* mechanism */ gss_OID_set * /* name_types */ /* */); OM_uint32 (*gss_inquire_context) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ gss_name_t *, /* src_name */ gss_name_t *, /* targ_name */ OM_uint32 *, /* lifetime_rec */ gss_OID *, /* mech_type */ OM_uint32 *, /* ctx_flags */ int *, /* locally_initiated */ int * /* open */ /* */); OM_uint32 (*gss_internal_release_oid) ( void *, /* context */ OM_uint32 *, /* minor_status */ gss_OID * /* OID */ /* */); OM_uint32 (*gss_wrap_size_limit) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ OM_uint32, /* req_output_size */ OM_uint32 * /* max_input_size */ /* */); OM_uint32 (*pname_to_uid) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* pname */ uid_t * /* uid */ /* */); OM_uint32 (*__gss_userok) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* pname */ const char *, /* local user */ int * /* user ok? */ /* */); OM_uint32 (*gss_export_name) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_buffer_t /* exported_name */ /* */); #endif /* ! _KERNEL */ OM_uint32 (*gss_sign) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ int, /* qop_req */ const gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); OM_uint32 (*gss_verify) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_buffer_t, /* message_buffer */ const gss_buffer_t, /* token_buffer */ int * /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 #endif /* */); #ifndef _KERNEL OM_uint32 (*gss_store_cred) ( void *, /* context */ OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred */ gss_cred_usage_t, /* cred_usage */ const gss_OID, /* desired_mech */ OM_uint32, /* overwrite_cred */ OM_uint32, /* default_cred */ gss_OID_set *, /* elements_stored */ gss_cred_usage_t * /* cred_usage_stored */ /* */); /* GGF extensions */ OM_uint32 (*gss_inquire_sec_context_by_oid) ( OM_uint32 *, /* minor_status */ const gss_ctx_id_t, /* context_handle */ const gss_OID, /* OID */ gss_buffer_set_t * /* data_set */ /* */); #endif } *gss_mechanism; #ifndef _KERNEL /* This structure MUST NOT be used by any code outside libgss */ typedef struct gss_config_ext { gss_acquire_cred_with_password_sfct gss_acquire_cred_with_password; } *gss_mechanism_ext; #endif /* _KERNEL */ /* * In the user space we use a wrapper structure to encompass the * mechanism entry points. The wrapper contain the mechanism * entry points and other data which is only relevant to the gss-api * layer. In the kernel we use only the gss_config strucutre because * the kernal does not cantain any of the extra gss-api specific data. */ typedef struct gss_mech_config { char *kmodName; /* kernel module name */ char *uLibName; /* user library name */ char *mechNameStr; /* mechanism string name */ char *optionStr; /* optional mech parameters */ void *dl_handle; /* RTLD object handle for the mech */ gss_OID mech_type; /* mechanism oid */ gss_mechanism mech; /* mechanism initialization struct */ #ifndef _KERNEL gss_mechanism_ext mech_ext; /* Solaris extensions */ #endif /* _KERNEL */ struct gss_mech_config *next; /* next element in the list */ } *gss_mech_info; /********************************************************/ /* Internal mechglue routines */ /* SUNW15resync - Solaris versions - replace w/mit ones? */ gss_mechanism __gss_get_mechanism(const gss_OID); #ifndef _KERNEL gss_mechanism_ext __gss_get_mechanism_ext(const gss_OID); #endif /* _KERNEL */ char *__gss_get_kmodName(const gss_OID); char *__gss_get_modOptions(const gss_OID); OM_uint32 __gss_import_internal_name(OM_uint32 *, const gss_OID, gss_union_name_t, gss_name_t *); OM_uint32 __gss_export_internal_name(OM_uint32 *, const gss_OID, const gss_name_t, gss_buffer_t); OM_uint32 __gss_display_internal_name(OM_uint32 *, const gss_OID, const gss_name_t, gss_buffer_t, gss_OID *); OM_uint32 __gss_release_internal_name(OM_uint32 *, const gss_OID, gss_name_t *); OM_uint32 gssint_delete_internal_sec_context (OM_uint32 *, gss_OID, gss_ctx_id_t *, gss_buffer_t); OM_uint32 __gss_convert_name_to_union_name( OM_uint32 *, /* minor_status */ gss_mechanism, /* mech */ gss_name_t, /* internal_name */ gss_name_t * /* external_name */ ); gss_cred_id_t __gss_get_mechanism_cred( const gss_union_cred_t, /* union_cred */ const gss_OID /* mech_type */ ); int gssint_mechglue_init(void); void gssint_mechglue_fini(void); gss_mechanism gssint_get_mechanism (gss_OID); OM_uint32 gssint_get_mech_type (gss_OID, gss_buffer_t); char *gssint_get_kmodName(const gss_OID); char *gssint_get_modOptions(const gss_OID); OM_uint32 gssint_import_internal_name (OM_uint32 *, gss_OID, gss_union_name_t, gss_name_t *); OM_uint32 gssint_export_internal_name(OM_uint32 *, const gss_OID, const gss_name_t, gss_buffer_t); OM_uint32 gssint_display_internal_name (OM_uint32 *, gss_OID, gss_name_t, gss_buffer_t, gss_OID *); OM_uint32 gssint_release_internal_name (OM_uint32 *, gss_OID, gss_name_t *); OM_uint32 gssint_convert_name_to_union_name (OM_uint32 *, /* minor_status */ gss_mechanism, /* mech */ gss_name_t, /* internal_name */ gss_name_t * /* external_name */ ); gss_cred_id_t gssint_get_mechanism_cred (gss_union_cred_t, /* union_cred */ gss_OID /* mech_type */ ); OM_uint32 gssint_create_copy_buffer( const gss_buffer_t, /* src buffer */ gss_buffer_t *, /* destination buffer */ int /* NULL terminate buffer ? */ ); OM_uint32 gssint_copy_oid_set( OM_uint32 *, /* minor_status */ const gss_OID_set_desc *, /* oid set */ gss_OID_set * /* new oid set */ ); /* SUNW15resync - for old Solaris version in libgss */ OM_uint32 gss_copy_oid_set( OM_uint32 *, /* minor_status */ const gss_OID_set_desc *, /* oid set */ gss_OID_set * /* new oid set */ ); gss_OID gss_find_mechanism_from_name_type (gss_OID); /* name_type */ OM_uint32 gss_add_mech_name_type (OM_uint32 *, /* minor_status */ gss_OID, /* name_type */ gss_OID /* mech */ ); /* * Sun extensions to GSS-API v2 */ OM_uint32 gssint_mech_to_oid( const char *mech, /* mechanism string name */ gss_OID *oid /* mechanism oid */ ); const char * gssint_oid_to_mech( const gss_OID oid /* mechanism oid */ ); OM_uint32 gssint_get_mechanisms( char *mechArray[], /* array to populate with mechs */ int arrayLen /* length of passed in array */ ); OM_uint32 gss_store_cred( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred_handle */ gss_cred_usage_t, /* cred_usage */ const gss_OID, /* desired_mech */ OM_uint32, /* overwrite_cred */ OM_uint32, /* default_cred */ gss_OID_set *, /* elements_stored */ gss_cred_usage_t * /* cred_usage_stored */ ); int gssint_get_der_length( unsigned char **, /* buf */ unsigned int, /* buf_len */ unsigned int * /* bytes */ ); unsigned int gssint_der_length_size(unsigned int /* len */); int gssint_put_der_length( unsigned int, /* length */ unsigned char **, /* buf */ unsigned int /* max_len */ ); /* Solaris kernel and gssd support */ /* * derived types for passing context and credential handles * between gssd and kernel */ typedef unsigned int gssd_ctx_id_t; typedef unsigned int gssd_cred_id_t; #define GSSD_NO_CONTEXT ((gssd_ctx_id_t)0) #define GSSD_NO_CREDENTIAL ((gssd_cred_id_t)0) #ifdef _KERNEL #ifndef _KRB5_H /* These macros are defined for Kerberos in krb5.h, and have priority */ #define MALLOC(n) kmem_alloc((n), KM_SLEEP) #define FREE(x, n) kmem_free((x), (n)) #endif /* _KRB5_H */ gss_mechanism __kgss_get_mechanism(gss_OID); void __kgss_add_mechanism(gss_mechanism); #endif /* _KERNEL */ struct kgss_cred { gssd_cred_id_t gssd_cred; OM_uint32 gssd_cred_verifier; }; #define KCRED_TO_KGSS_CRED(cred) ((struct kgss_cred *)(cred)) #define KCRED_TO_CRED(cred) (KCRED_TO_KGSS_CRED(cred)->gssd_cred) #define KCRED_TO_CREDV(cred) (KCRED_TO_KGSS_CRED(cred)->gssd_cred_verifier) struct kgss_ctx { gssd_ctx_id_t gssd_ctx; #ifdef _KERNEL gss_ctx_id_t gssd_i_ctx; bool_t ctx_imported; gss_mechanism mech; #endif /* _KERNEL */ OM_uint32 gssd_ctx_verifier; }; #define KCTX_TO_KGSS_CTX(ctx) ((struct kgss_ctx *)(ctx)) #define KCTX_TO_CTX_IMPORTED(ctx) (KCTX_TO_KGSS_CTX(ctx)->ctx_imported) #define KCTX_TO_GSSD_CTX(ctx) (KCTX_TO_KGSS_CTX(ctx)->gssd_ctx) #define KCTX_TO_CTXV(ctx) (KCTX_TO_KGSS_CTX(ctx)->gssd_ctx_verifier) #define KCTX_TO_MECH(ctx) (KCTX_TO_KGSS_CTX(ctx)->mech) #define KCTX_TO_PRIVATE(ctx) (KCTX_TO_MECH(ctx)->context) #define KGSS_CTX_TO_GSSD_CTX(ctx) \ (((ctx) == GSS_C_NO_CONTEXT) ? (gssd_ctx_id_t)(uintptr_t)(ctx) : \ KCTX_TO_GSSD_CTX(ctx)) #define KGSS_CTX_TO_GSSD_CTXV(ctx) \ (((ctx) == GSS_C_NO_CONTEXT) ? (0) : KCTX_TO_CTXV(ctx)) #ifdef _KERNEL #define KCTX_TO_I_CTX(ctx) (KCTX_TO_KGSS_CTX(ctx)->gssd_i_ctx) #define KCTX_TO_CTX(ctx) \ ((KCTX_TO_CTX_IMPORTED(ctx) == FALSE) ? (ctx) : \ KCTX_TO_I_CTX(ctx)) #define KGSS_CRED_ALLOC() kmem_zalloc(sizeof (struct kgss_cred), \ KM_SLEEP) #define KGSS_CRED_FREE(cred) kmem_free(cred, sizeof (struct kgss_cred)) #define KGSS_ALLOC() kmem_zalloc(sizeof (struct kgss_ctx), KM_SLEEP) #define KGSS_FREE(ctx) kmem_free(ctx, sizeof (struct kgss_ctx)) #define KGSS_SIGN(minor_st, ctx, qop, msg, tkn) \ (*(KCTX_TO_MECH(ctx)->gss_sign))(KCTX_TO_PRIVATE(ctx), minor_st, \ KCTX_TO_CTX(ctx), qop, msg, tkn, KCTX_TO_CTXV(ctx)) #define KGSS_VERIFY(minor_st, ctx, msg, tkn, qop) \ (*(KCTX_TO_MECH(ctx)->gss_verify))(KCTX_TO_PRIVATE(ctx), minor_st,\ KCTX_TO_CTX(ctx), msg, tkn, qop, KCTX_TO_CTXV(ctx)) #define KGSS_DELETE_SEC_CONTEXT(minor_st, ctx, int_ctx_id, tkn) \ (*(KCTX_TO_MECH(ctx)->gss_delete_sec_context))(KCTX_TO_PRIVATE(ctx),\ minor_st, int_ctx_id, tkn, KCTX_TO_CTXV(ctx)) #define KGSS_IMPORT_SEC_CONTEXT(minor_st, tkn, ctx, int_ctx_id) \ (*(KCTX_TO_MECH(ctx)->gss_import_sec_context))(KCTX_TO_PRIVATE(ctx),\ minor_st, tkn, int_ctx_id) #define KGSS_SEAL(minor_st, ctx, conf_req, qop, msg, conf_state, tkn) \ (*(KCTX_TO_MECH(ctx)->gss_seal))(KCTX_TO_PRIVATE(ctx), minor_st, \ KCTX_TO_CTX(ctx), conf_req, qop, msg, conf_state, tkn,\ KCTX_TO_CTXV(ctx)) #define KGSS_UNSEAL(minor_st, ctx, msg, tkn, conf, qop) \ (*(KCTX_TO_MECH(ctx)->gss_unseal))(KCTX_TO_PRIVATE(ctx), minor_st,\ KCTX_TO_CTX(ctx), msg, tkn, conf, qop, \ KCTX_TO_CTXV(ctx)) #define KGSS_INIT_CONTEXT(ctx) krb5_init_context(ctx) #define KGSS_RELEASE_OID(minor_st, oid) krb5_gss_release_oid(minor_st, oid) extern OM_uint32 kgss_release_oid(OM_uint32 *, gss_OID *); #else /* !_KERNEL */ #define KGSS_INIT_CONTEXT(ctx) krb5_gss_init_context(ctx) #define KGSS_RELEASE_OID(minor_st, oid) gss_release_oid(minor_st, oid) #define KCTX_TO_CTX(ctx) (KCTX_TO_KGSS_CTX(ctx)->gssd_ctx) #define MALLOC(n) malloc(n) #define FREE(x, n) free(x) #define KGSS_CRED_ALLOC() (struct kgss_cred *) \ MALLOC(sizeof (struct kgss_cred)) #define KGSS_CRED_FREE(cred) free(cred) #define KGSS_ALLOC() (struct kgss_ctx *)MALLOC(sizeof (struct kgss_ctx)) #define KGSS_FREE(ctx) free(ctx) #define KGSS_SIGN(minor_st, ctx, qop, msg, tkn) \ kgss_sign_wrapped(minor_st, \ KCTX_TO_CTX(ctx), qop, msg, tkn, KCTX_TO_CTXV(ctx)) #define KGSS_VERIFY(minor_st, ctx, msg, tkn, qop) \ kgss_verify_wrapped(minor_st,\ KCTX_TO_CTX(ctx), msg, tkn, qop, KCTX_TO_CTXV(ctx)) #define KGSS_SEAL(minor_st, ctx, conf_req, qop, msg, conf_state, tkn) \ kgss_seal_wrapped(minor_st, \ KCTX_TO_CTX(ctx), conf_req, qop, msg, conf_state, tkn, \ KCTX_TO_CTXV(ctx)) #define KGSS_UNSEAL(minor_st, ctx, msg, tkn, conf, qop) \ kgss_unseal_wrapped(minor_st,\ KCTX_TO_CTX(ctx), msg, tkn, conf, qop, \ KCTX_TO_CTXV(ctx)) #endif /* _KERNEL */ /* SUNW15resync - moved from gssapiP_generic.h for sake of non-krb5 mechs */ OM_uint32 generic_gss_release_buffer (OM_uint32*, /* minor_status */ gss_buffer_t /* buffer */ ); OM_uint32 generic_gss_release_oid_set (OM_uint32*, /* minor_status */ gss_OID_set* /* set */ ); OM_uint32 generic_gss_release_oid (OM_uint32*, /* minor_status */ gss_OID* /* set */ ); OM_uint32 generic_gss_copy_oid (OM_uint32 *, /* minor_status */ gss_OID_desc * const, /* oid */ /* SUNW15resync */ gss_OID * /* new_oid */ ); OM_uint32 generic_gss_create_empty_oid_set (OM_uint32 *, /* minor_status */ gss_OID_set * /* oid_set */ ); OM_uint32 generic_gss_add_oid_set_member (OM_uint32 *, /* minor_status */ gss_OID_desc * const, /* member_oid */ gss_OID_set * /* oid_set */ ); OM_uint32 generic_gss_test_oid_set_member (OM_uint32 *, /* minor_status */ gss_OID_desc * const, /* member */ gss_OID_set, /* set */ int * /* present */ ); OM_uint32 generic_gss_oid_to_str (OM_uint32 *, /* minor_status */ gss_OID_desc * const, /* oid */ gss_buffer_t /* oid_str */ ); OM_uint32 generic_gss_str_to_oid (OM_uint32 *, /* minor_status */ gss_buffer_t, /* oid_str */ gss_OID * /* oid */ ); OM_uint32 generic_gss_oid_compose( OM_uint32 *, /* minor_status */ const char *, /* prefix */ size_t, /* prefix_len */ int, /* suffix */ gss_OID_desc *); /* oid */ OM_uint32 generic_gss_oid_decompose( OM_uint32 *, /* minor_status */ const char *, /*prefix */ size_t, /* prefix_len */ gss_OID_desc *, /* oid */ int *); /* suffix */ OM_uint32 generic_gss_create_empty_buffer_set (OM_uint32 * /*minor_status*/, gss_buffer_set_t * /*buffer_set*/); OM_uint32 generic_gss_add_buffer_set_member (OM_uint32 * /*minor_status*/, const gss_buffer_t /*member_buffer*/, gss_buffer_set_t * /*buffer_set*/); OM_uint32 generic_gss_release_buffer_set (OM_uint32 * /*minor_status*/, gss_buffer_set_t * /*buffer_set*/); /* * SUNW17PACresync * New map error API in MIT 1.7, at build time generates code for errors. * Solaris does not gen the errors at build time so we just stub these * for now, need to revisit. * See mglueP.h and util_errmap.c in MIT 1.7. */ #ifdef _KERNEL #define map_error(MINORP, MECH) #define map_errcode(MINORP) #else /* _KERNEL */ /* Use this to map an error code that was returned from a mech operation; the mech will be asked to produce the associated error messages. Remember that if the minor status code cannot be returned to the caller (e.g., if it's stuffed in an automatic variable and then ignored), then we don't care about producing a mapping. */ #define map_error(MINORP, MECH) \ (*(MINORP) = gssint_mecherrmap_map(*(MINORP), &(MECH)->mech_type)) #define map_error_oid(MINORP, MECHOID) \ (*(MINORP) = gssint_mecherrmap_map(*(MINORP), (MECHOID))) /* Use this to map an errno value or com_err error code being generated within the mechglue code (e.g., by calling generic oid ops). Any errno or com_err values produced by mech operations should be processed with map_error. This means they'll be stored separately even if the mech uses com_err, because we can't assume that it will use com_err. */ #define map_errcode(MINORP) \ (*(MINORP) = gssint_mecherrmap_map_errcode(*(MINORP))) #endif /* _KERNEL */ #endif /* _GSS_MECHGLUEP_H */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * SUNW15resync * This file (mglueP.h) is the MIT name for the mech glue * header file, but the Solaris one is mechglueP.h. We keep this file * so MIT files don't need to be changed to include the Solaris one. */ #include "mechglueP.h" /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _KGSSAPI_DEFS_H #define _KGSSAPI_DEFS_H #ifdef __cplusplus extern "C" { #endif #include extern kmutex_t gssrpcb_lock; extern kmutex_t __kgss_mech_lock; extern zone_key_t gss_zone_key; extern void *gss_zone_init(zoneid_t); extern void gss_zone_fini(zoneid_t, void *); /* * GSSLOG debugging for kgss module. */ #if defined(DEBUG) && !defined(GSSDEBUG) #define GSSDEBUG #endif #ifdef GSSDEBUG extern uint_t gss_log; #include #define GSSLOG(A, B, C) \ ((void)((gss_log & (A)) && (printf((B), (C)), TRUE))) #define GSSLOG0(A, B) \ ((void)((gss_log & (A)) && (printf(B), TRUE))) #else #define GSSLOG(A, B, C) #define GSSLOG0(A, B) #endif #ifdef __cplusplus } #endif #endif /* _KGSSAPI_DEFS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. */ /* * A module that implements a dummy security mechanism. * It's mainly used to test GSS-API application. Multiple tokens * exchanged during security context establishment can be * specified through dummy_mech.conf located in /etc. */ #include #include #include #include #include #include #include #include #ifdef DUMMY_MECH_DEBUG /* * Kernel kgssd module debugging aid. The global variable "dummy_mech_log" * is a bit mask which allows various types of debugging messages * to be printed out. * * dummy_mech_log & 1 will cause actual failures to be printed. * dummy_mech_log & 2 will cause informational messages to be * printed on the client side of kgssd. * dummy_mech_log & 4 will cause informational messages to be * printed on the server side of kgssd. * dummy_mech_log & 8 will cause informational messages to be * printed on both client and server side of kgssd. */ uint_t dummy_mech_log = 1; #endif /* Local defines */ #define MAGIC_TOKEN_NUMBER 12345 /* private routines for dummy_mechanism */ static gss_buffer_desc make_dummy_token_msg(void *data, int datalen); static int der_length_size(int); static void der_write_length(unsigned char **, int); static int der_read_length(unsigned char **, int *); static int g_token_size(gss_OID mech, unsigned int body_size); static void g_make_token_header(gss_OID mech, int body_size, unsigned char **buf, int tok_type); static int g_verify_token_header(gss_OID mech, int *body_size, unsigned char **buf_in, int tok_type, int toksize); /* private global variables */ static int dummy_token_nums; /* * This OID: * { iso(1) org(3) internet(6) dod(1) private(4) enterprises(1) sun(42) * products(2) gssapi(26) mechtypes(1) dummy(2) } */ static struct gss_config dummy_mechanism = {{10, "\053\006\001\004\001\052\002\032\001\002"}, NULL, /* context */ NULL, /* next */ TRUE, /* uses_kmod */ dummy_gss_unseal, dummy_gss_delete_sec_context, dummy_gss_seal, dummy_gss_import_sec_context, dummy_gss_sign, dummy_gss_verify }; static gss_mechanism gss_mech_initialize() { dprintf("Entering gss_mech_initialize\n"); if (dummy_token_nums == 0) dummy_token_nums = 1; dprintf("Leaving gss_mech_initialize\n"); return (&dummy_mechanism); } /* * Clean up after a failed mod_install() */ static void gss_mech_fini() { /* Nothing to do */ } /* * Module linkage information for the kernel. */ extern struct mod_ops mod_miscops; static struct modlmisc modlmisc = { &mod_miscops, "in-kernel dummy GSS mechanism" }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modlmisc, NULL }; static int dummy_fini_code = EBUSY; int _init() { int retval; gss_mechanism mech, tmp; mech = gss_mech_initialize(); mutex_enter(&__kgss_mech_lock); tmp = __kgss_get_mechanism(&mech->mech_type); if (tmp != NULL) { DUMMY_MECH_LOG0(8, "dummy GSS mechanism: mechanism already in table.\n"); if (tmp->uses_kmod == TRUE) { DUMMY_MECH_LOG0(8, "dummy GSS mechanism: mechanism " "table supports kernel operations!\n"); } /* * keep us loaded, but let us be unloadable. This * will give the developer time to trouble shoot */ dummy_fini_code = 0; } else { __kgss_add_mechanism(mech); ASSERT(__kgss_get_mechanism(&mech->mech_type) == mech); } mutex_exit(&__kgss_mech_lock); if ((retval = mod_install(&modlinkage)) != 0) gss_mech_fini(); /* clean up */ return (retval); } int _fini() { int ret = dummy_fini_code; if (ret == 0) { ret = (mod_remove(&modlinkage)); } return (ret); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } /*ARGSUSED*/ static OM_uint32 dummy_gss_sign(context, minor_status, context_handle, qop_req, message_buffer, message_token, gssd_ctx_verifier) void *context; OM_uint32 *minor_status; gss_ctx_id_t context_handle; int qop_req; gss_buffer_t message_buffer; gss_buffer_t message_token; OM_uint32 gssd_ctx_verifier; { dummy_gss_ctx_id_rec *ctx; char token_string[] = "dummy_gss_sign"; dprintf("Entering gss_sign\n"); if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_NO_CONTEXT); ctx = (dummy_gss_ctx_id_rec *) context_handle; ASSERT(ctx->established == 1); ASSERT(ctx->token_number == MAGIC_TOKEN_NUMBER); *message_token = make_dummy_token_msg( token_string, strlen(token_string)); dprintf("Leaving gss_sign\n"); return (GSS_S_COMPLETE); } /*ARGSUSED*/ static OM_uint32 dummy_gss_verify(context, minor_status, context_handle, message_buffer, token_buffer, qop_state, gssd_ctx_verifier) void *context; OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t message_buffer; gss_buffer_t token_buffer; int *qop_state; OM_uint32 gssd_ctx_verifier; { unsigned char *ptr; int bodysize; int err; dummy_gss_ctx_id_rec *ctx; dprintf("Entering gss_verify\n"); if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_NO_CONTEXT); ctx = (dummy_gss_ctx_id_rec *) context_handle; ASSERT(ctx->established == 1); ASSERT(ctx->token_number == MAGIC_TOKEN_NUMBER); /* Check for defective input token. */ ptr = (unsigned char *) token_buffer->value; if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize, &ptr, 0, token_buffer->length)) { *minor_status = err; return (GSS_S_DEFECTIVE_TOKEN); } *qop_state = GSS_C_QOP_DEFAULT; dprintf("Leaving gss_verify\n"); return (GSS_S_COMPLETE); } /*ARGSUSED*/ static OM_uint32 dummy_gss_seal(context, minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, gssd_ctx_verifier) void *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; OM_uint32 gssd_ctx_verifier; { gss_buffer_desc output; dummy_gss_ctx_id_rec *ctx; dprintf("Entering gss_seal\n"); if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_NO_CONTEXT); ctx = (dummy_gss_ctx_id_rec *) context_handle; ASSERT(ctx->established == 1); ASSERT(ctx->token_number == MAGIC_TOKEN_NUMBER); /* Copy the input message to output message */ output = make_dummy_token_msg( input_message_buffer->value, input_message_buffer->length); if (conf_state) *conf_state = 1; *output_message_buffer = output; dprintf("Leaving gss_seal\n"); return (GSS_S_COMPLETE); } /*ARGSUSED*/ static OM_uint32 dummy_gss_unseal(context, minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state, gssd_ctx_verifier) void *context; OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t input_message_buffer; gss_buffer_t output_message_buffer; int *conf_state; int *qop_state; OM_uint32 gssd_ctx_verifier; { gss_buffer_desc output; dummy_gss_ctx_id_rec *ctx; unsigned char *ptr; int bodysize; int err; dprintf("Entering gss_unseal\n"); if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_NO_CONTEXT); ctx = (dummy_gss_ctx_id_rec *) context_handle; ASSERT(ctx->established == 1); ASSERT(ctx->token_number == MAGIC_TOKEN_NUMBER); ptr = (unsigned char *) input_message_buffer->value; if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize, &ptr, 0, input_message_buffer->length)) { *minor_status = err; return (GSS_S_DEFECTIVE_TOKEN); } output.length = bodysize; output.value = (void *)MALLOC(output.length); (void) memcpy(output.value, ptr, output.length); *output_message_buffer = output; *qop_state = GSS_C_QOP_DEFAULT; if (conf_state) *conf_state = 1; dprintf("Leaving gss_unseal\n"); return (GSS_S_COMPLETE); } /*ARGSUSED*/ OM_uint32 dummy_gss_import_sec_context(ct, minor_status, interprocess_token, context_handle) void *ct; OM_uint32 *minor_status; gss_buffer_t interprocess_token; gss_ctx_id_t *context_handle; { unsigned char *ptr; int bodysize; int err; /* Assume that we got ctx from the interprocess token. */ dummy_gss_ctx_id_t ctx; dprintf("Entering import_sec_context\n"); ptr = (unsigned char *) interprocess_token->value; if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize, &ptr, 0, interprocess_token->length)) { *minor_status = err; return (GSS_S_DEFECTIVE_TOKEN); } ctx = (dummy_gss_ctx_id_t)MALLOC(sizeof (dummy_gss_ctx_id_rec)); ctx->token_number = MAGIC_TOKEN_NUMBER; ctx->established = 1; *context_handle = (gss_ctx_id_t)ctx; dprintf("Leaving import_sec_context\n"); return (GSS_S_COMPLETE); } /*ARGSUSED*/ static OM_uint32 dummy_gss_delete_sec_context(ct, minor_status, context_handle, output_token, gssd_ctx_verifier) void *ct; OM_uint32 *minor_status; gss_ctx_id_t *context_handle; gss_buffer_t output_token; OM_uint32 gssd_ctx_verifier; { dummy_gss_ctx_id_t ctx; dprintf("Entering delete_sec_context\n"); /* Make the length to 0, so the output token is not sent to peer */ if (output_token) { output_token->length = 0; output_token->value = NULL; } if (*context_handle == GSS_C_NO_CONTEXT) { *minor_status = 0; return (GSS_S_COMPLETE); } ctx = (dummy_gss_ctx_id_rec *) *context_handle; ASSERT(ctx->established == 1); ASSERT(ctx->token_number == MAGIC_TOKEN_NUMBER); FREE(ctx, sizeof (dummy_gss_ctx_id_rec)); *context_handle = GSS_C_NO_CONTEXT; dprintf("Leaving delete_sec_context\n"); return (GSS_S_COMPLETE); } static int der_length_size(int length) { if (length < (1<<7)) return (1); else if (length < (1<<8)) return (2); else if (length < (1<<16)) return (3); else if (length < (1<<24)) return (4); else return (5); } static void der_write_length(unsigned char ** buf, int length) { if (length < (1<<7)) { *(*buf)++ = (unsigned char) length; } else { *(*buf)++ = (unsigned char) (der_length_size(length)+127); if (length >= (1<<24)) *(*buf)++ = (unsigned char) (length>>24); if (length >= (1<<16)) *(*buf)++ = (unsigned char) ((length>>16)&0xff); if (length >= (1<<8)) *(*buf)++ = (unsigned char) ((length>>8)&0xff); *(*buf)++ = (unsigned char) (length&0xff); } } static int der_read_length(buf, bufsize) unsigned char **buf; int *bufsize; { unsigned char sf; int ret; if (*bufsize < 1) return (-1); sf = *(*buf)++; (*bufsize)--; if (sf & 0x80) { if ((sf &= 0x7f) > ((*bufsize)-1)) return (-1); if (sf > DUMMY_SIZE_OF_INT) return (-1); ret = 0; for (; sf; sf--) { ret = (ret<<8) + (*(*buf)++); (*bufsize)--; } } else { ret = sf; } return (ret); } static int g_token_size(mech, body_size) gss_OID mech; unsigned int body_size; { /* set body_size to sequence contents size */ body_size += 4 + (int)mech->length; /* NEED overflow check */ return (1 + der_length_size(body_size) + body_size); } static void g_make_token_header(mech, body_size, buf, tok_type) gss_OID mech; int body_size; unsigned char **buf; int tok_type; { *(*buf)++ = 0x60; der_write_length(buf, 4 + mech->length + body_size); *(*buf)++ = 0x06; *(*buf)++ = (unsigned char) mech->length; TWRITE_STR(*buf, mech->elements, ((int)mech->length)); *(*buf)++ = (unsigned char) ((tok_type>>8)&0xff); *(*buf)++ = (unsigned char) (tok_type&0xff); } static int g_verify_token_header(mech, body_size, buf_in, tok_type, toksize) gss_OID mech; int *body_size; unsigned char **buf_in; int tok_type; int toksize; { unsigned char *buf = *buf_in; int seqsize; gss_OID_desc toid; int ret = 0; if ((toksize -= 1) < 0) return (G_BAD_TOK_HEADER); if (*buf++ != 0x60) return (G_BAD_TOK_HEADER); if ((seqsize = der_read_length(&buf, &toksize)) < 0) return (G_BAD_TOK_HEADER); if (seqsize != toksize) return (G_BAD_TOK_HEADER); if ((toksize -= 1) < 0) return (G_BAD_TOK_HEADER); if (*buf++ != 0x06) return (G_BAD_TOK_HEADER); if ((toksize -= 1) < 0) return (G_BAD_TOK_HEADER); toid.length = *buf++; if ((toksize -= toid.length) < 0) return (G_BAD_TOK_HEADER); toid.elements = buf; buf += toid.length; if (! g_OID_equal(&toid, mech)) ret = G_WRONG_MECH; /* * G_WRONG_MECH is not returned immediately because it's more important * to return G_BAD_TOK_HEADER if the token header is in fact bad */ if ((toksize -= 2) < 0) return (G_BAD_TOK_HEADER); if ((*buf++ != ((tok_type>>8)&0xff)) || (*buf++ != (tok_type&0xff))) return (G_BAD_TOK_HEADER); if (!ret) { *buf_in = buf; *body_size = toksize; } return (ret); } static gss_buffer_desc make_dummy_token_msg(void *data, int dataLen) { gss_buffer_desc buffer; int tlen; unsigned char *t; unsigned char *ptr; if (data == NULL) { buffer.length = 0; buffer.value = NULL; return (buffer); } tlen = g_token_size((gss_OID)gss_mech_dummy, dataLen); t = (unsigned char *) MALLOC(tlen); ptr = t; g_make_token_header((gss_OID)gss_mech_dummy, dataLen, &ptr, 0); (void) memcpy(ptr, data, dataLen); buffer.length = tlen; buffer.value = (void *) t; return (buffer); } * Copyright 1989,1990,1995 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. 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 1987-2004 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * Copyright (C) 1989-1995 by the Massachusetts Institute of Technology, * Cambridge, MA, USA. All Rights Reserved. * * This software is being provided to you, the LICENSEE, by the * Massachusetts Institute of Technology (M.I.T.) under the following * license. By obtaining, using and/or copying this software, you agree * that you have read, understood, and will comply with these terms and * conditions: * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute * this software and its documentation for any purpose and without fee or * royalty is hereby granted, provided that you agree to comply with the * following copyright notice and statements, including the disclaimer, and * that the same appear on ALL copies of the software and documentation, * including modifications that you make for internal use or for * distribution: * * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. * * The name of the Massachusetts Institute of Technology or M.I.T. may NOT * be used in advertising or publicity pertaining to distribution of the * software. Title to copyright in this software and any associated * documentation shall at all times remain with M.I.T., and USER agrees to * preserve same. ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD4 Message ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD4 Message Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** * Copyright 1993,1995 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the software, * derivative works or modified versions, and any portions thereof. * * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER * RESULTING FROM THE USE OF THIS SOFTWARE. * Copyright 1995 by Richard P. Basch. All Rights Reserved. * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Richard P. Basch, * Lehman Brothers and M.I.T. make no representations about the suitability * of this software for any purpose. It is provided "as is" without * express or implied warranty. PORTIONS OF KERBEROS MECHANISM FOR GENERIC SECURITY SERVICES (KERNEL) /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). This cipher is widely believed and has been tested to be equivalent with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark of RSA Data Security) */ #include #include /* salt string used for exportable ARCFOUR */ static const char *l40 = "fortybits"; void krb5_arcfour_encrypt_length(enc, hash, inputlen, length) const struct krb5_enc_provider *enc; const struct krb5_hash_provider *hash; size_t inputlen; size_t *length; { size_t blocksize, hashsize; blocksize = enc->block_size; hashsize = hash->hashsize; /* checksum + (confounder + inputlen, in even blocksize) */ *length = hashsize + krb5_roundup(8 + inputlen, blocksize); } krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage) { switch (usage) { case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ return 1; case 2: /* ticket from kdc */ return 2; case 3: /* as-rep encrypted part */ return 8; case 4: /* tgs-req authz data */ return 4; case 5: /* tgs-req authz data in subkey */ return 5; case 6: /* tgs-req authenticator cksum */ return 6; case 7: /* tgs-req authenticator */ return 7; case 8: return 8; case 9: /* tgs-rep encrypted with subkey */ return 8; case 10: /* ap-rep authentication cksum */ return 10; /* xxx Microsoft never uses this*/ case 11: /* app-req authenticator */ return 11; case 12: /* app-rep encrypted part */ return 12; case 23: /* sign wrap token*/ return 13; default: return usage; } } krb5_error_code krb5_arcfour_encrypt(context, enc, hash, key, usage, ivec, input, output) krb5_context context; const struct krb5_enc_provider *enc; const struct krb5_hash_provider *hash; const krb5_keyblock *key; krb5_keyusage usage; const krb5_data *ivec; const krb5_data *input; krb5_data *output; { krb5_keyblock k1, k2, k3; krb5_keyblock *kptr; krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; krb5_keyusage ms_usage; size_t keybytes, blocksize, hashsize; krb5_error_code ret = 0; blocksize = enc->block_size; keybytes = enc->keybytes; hashsize = hash->hashsize; bzero(&d2, sizeof(krb5_data)); bzero(&k2, sizeof(krb5_keyblock)); /* * d1 is the contents buffer for key k1. * k1 = HMAC(input_key, salt) */ d1.length=keybytes; d1.data=MALLOC(d1.length); if (d1.data == NULL) return (ENOMEM); bcopy(key, &k1, sizeof (krb5_keyblock)); k1.length=d1.length; k1.contents= (void *) d1.data; /* * d2 is the contents of key 'k2', which is used to generate the * checksum field. 'd2' == 'd1' when not using the exportable * enctype. This is only needed when using the exportable * enctype. */ if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { d2.length=keybytes; d2.data=MALLOC(d2.length); if (d2.data == NULL) { FREE(d1.data, d1.length); return (ENOMEM); } bcopy(key, &k2, sizeof (krb5_keyblock)); k2.length=d2.length; k2.contents=(void *) d2.data; } /* * d3 will hold the contents of the final key used for the * encryption step. 'k3' is the key structure that has 'd3' * as its 'contents' field. * k3 = HMAC(k1, checksum) */ d3.length=keybytes; d3.data=MALLOC(d3.length); if (d3.data == NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); return (ENOMEM); } bcopy(key, &k3, sizeof (krb5_keyblock)); k3.length=d3.length; k3.contents= (void *) d3.data; salt.length=14; salt.data=MALLOC(salt.length); if (salt.data == NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); FREE(d3.data, d3.length); return (ENOMEM); } /* is "input" already blocksize aligned? if it is, then we need this step, otherwise we do not */ plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); plaintext.data=MALLOC(plaintext.length); if (plaintext.data == NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); FREE(d3.data, d3.length); FREE(salt.data, salt.length); return(ENOMEM); } bzero(plaintext.data, plaintext.length); /* setup convienient pointers into the allocated data */ checksum.length=hashsize; checksum.data=output->data; ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); ciphertext.data=output->data+hashsize; confounder.length=CONFOUNDERLENGTH; confounder.data=plaintext.data; output->length = plaintext.length+hashsize; /* begin the encryption, computer K1 */ ms_usage=krb5int_arcfour_translate_usage(usage); if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { (void) strncpy(salt.data, l40, salt.length); salt.data[10]=ms_usage & 0xff; salt.data[11]=(ms_usage >> 8) & 0xff; salt.data[12]=(ms_usage >> 16) & 0xff; salt.data[13]=(ms_usage >> 24) & 0xff; } else { salt.length=4; salt.data[0]=ms_usage & 0xff; salt.data[1]=(ms_usage >> 8) & 0xff; salt.data[2]=(ms_usage >> 16) & 0xff; salt.data[3]=(ms_usage >> 24) & 0xff; } #ifdef _KERNEL ret = krb5_hmac(context, key, &salt, &d1); #else ret = krb5_hmac(context, hash, key, 1, &salt, &d1); #endif /* _KERNEL */ if (ret != 0) goto cleanup; if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { bcopy(k1.contents, k2.contents, k2.length); (void) memset(k1.contents+7, 0xab, 9); kptr = &k2; } else { kptr = &k1; } /* create a confounder block */ ret=krb5_c_random_make_octets(context, &confounder); bcopy(input->data, plaintext.data+confounder.length, input->length); if (ret) goto cleanup; /* * Compute the HMAC checksum field. * checksum = HMAC(k1/k2, plaintext); * k2 used when key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP */ #ifdef _KERNEL ret = krb5_hmac(context, kptr, &plaintext, &checksum); #else ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &checksum); #endif /* _KERNEL */ if (ret) goto cleanup; /* * The final encryption key is the HMAC of the checksum * using k1 * * k3 = HMAC(k1, checksum); * == or (in other terms) == * k3 = HMAC((HMAC(input_key,salt), HMAC(k1, plaintext)); */ #ifdef _KERNEL ret = krb5_hmac(context, &k1, &checksum, &d3); #else ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); #endif /* _KERNEL */ if (ret) goto cleanup; ret = (*(enc->encrypt))(context, &k3, ivec, &plaintext, &ciphertext); cleanup: bzero(d1.data, d1.length); if (d2.data) { bzero(d2.data, d2.length); FREE(d2.data, d2.length); } bzero(d3.data, d3.length); bzero(salt.data, salt.length); bzero(plaintext.data, plaintext.length); FREE(d1.data, d1.length); FREE(d3.data, d3.length); FREE(salt.data, salt.length); FREE(plaintext.data, plaintext.length); return (ret); } /* This is the arcfour-hmac decryption routine */ krb5_error_code krb5_arcfour_decrypt(context, enc, hash, key, usage, ivec, input, output) krb5_context context; const struct krb5_enc_provider *enc; const struct krb5_hash_provider *hash; const krb5_keyblock *key; krb5_keyusage usage; const krb5_data *ivec; const krb5_data *input; krb5_data *output; { krb5_keyblock k1,k2,k3, *kptr; krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; krb5_keyusage ms_usage; size_t keybytes, hashsize; krb5_error_code ret; keybytes = enc->keybytes; hashsize = hash->hashsize; /* Verify input and output lengths. */ if (input->length < hashsize + CONFOUNDERLENGTH) return KRB5_BAD_MSIZE; if (output->length < input->length - hashsize - CONFOUNDERLENGTH) return KRB5_BAD_MSIZE; bzero(&d2, sizeof(krb5_data)); bzero(&k2, sizeof(krb5_keyblock)); /* * d1 is the contents buffer for key k1. * k1 = HMAC(input_key, salt) */ d1.length=keybytes; d1.data=MALLOC(d1.length); if (d1.data == NULL) return (ENOMEM); (void) bcopy(key, &k1, sizeof (krb5_keyblock)); k1.length=d1.length; k1.contents= (void *) d1.data; /* * d2 is the contents of key 'k2', which is used to generate the * checksum field. 'd2' == 'd1' when not using the exportable * enctype. This is only needed when using the exportable * enctype. */ if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { d2.length=keybytes; d2.data=MALLOC(d2.length); if (d2.data == NULL) { FREE(d1.data, d1.length); return (ENOMEM); } (void) bcopy(key, &k2, sizeof(krb5_keyblock)); k2.length=d2.length; k2.contents= (void *) d2.data; } /* * d3 will hold the contents of the final key used for the * encryption step. 'k3' is the key structure that has 'd3' * as its 'contents' field. * k3 = HMAC(k1, checksum) */ d3.length=keybytes; d3.data=MALLOC(d3.length); if (d3.data == NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); return (ENOMEM); } bcopy(key, &k3, sizeof(krb5_keyblock)); k3.length=d3.length; k3.contents= (void *) d3.data; salt.length=14; salt.data=MALLOC(salt.length); if(salt.data==NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); FREE(d3.data, d3.length); return (ENOMEM); } ciphertext.length=input->length-hashsize; ciphertext.data=input->data+hashsize; plaintext.length=ciphertext.length; plaintext.data=MALLOC(plaintext.length); if (plaintext.data == NULL) { FREE(d1.data, d1.length); if (d2.data) FREE(d2.data, d2.length); FREE(d3.data, d3.length); FREE(salt.data, salt.length); return (ENOMEM); } checksum.length=hashsize; checksum.data=input->data; /* compute the salt */ ms_usage=krb5int_arcfour_translate_usage(usage); if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { (void) strncpy(salt.data, l40, salt.length); salt.data[10]=ms_usage & 0xff; salt.data[11]=(ms_usage>>8) & 0xff; salt.data[12]=(ms_usage>>16) & 0xff; salt.data[13]=(ms_usage>>24) & 0xff; } else { salt.length=4; salt.data[0]=ms_usage & 0xff; salt.data[1]=(ms_usage>>8) & 0xff; salt.data[2]=(ms_usage>>16) & 0xff; salt.data[3]=(ms_usage>>24) & 0xff; } #ifdef _KERNEL ret=krb5_hmac(context, key, &salt, &d1); #else ret=krb5_hmac(context, hash, key, 1, &salt, &d1); #endif /* _KERNEL */ if (ret) goto cleanup; if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { bcopy(k1.contents, k2.contents, d1.length); (void) memset(k1.contents+7, 0xab, 9); kptr = &k2; } else { kptr = &k1; } #ifdef _KERNEL ret = krb5_hmac(context, &k1, &checksum, &d3); #else ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); #endif /* _KERNEL */ if (ret) goto cleanup; ret=(*(enc->decrypt))(context, &k3, ivec, &ciphertext, &plaintext); if (ret) goto cleanup; #ifdef _KERNEL ret = krb5_hmac(context, kptr, &plaintext, &d1); #else ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &d1); #endif /* _KERNEL */ if (ret) goto cleanup; if (bcmp(checksum.data, d1.data, hashsize) != 0) { ret=KRB5KRB_AP_ERR_BAD_INTEGRITY; goto cleanup; } bcopy(plaintext.data+CONFOUNDERLENGTH, output->data, (plaintext.length-CONFOUNDERLENGTH)); output->length=plaintext.length-CONFOUNDERLENGTH; cleanup: bzero(d1.data, d1.length); if (d2.data) { bzero(d2.data, d2.length); FREE(d2.data, d2.length); } bzero(d3.data, d2.length); bzero(salt.data, salt.length); bzero(plaintext.data, plaintext.length); FREE(d1.data, d1.length); FREE(d3.data, d3.length); FREE(salt.data, salt.length); FREE(plaintext.data, plaintext.length); return (ret); } /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "etypes.h" /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_block_size(krb5_context context, krb5_enctype enctype, size_t *blocksize) { int i; for (i=0; iblock_size; return(0); } /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "cksumtypes.h" /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, size_t *length) { int i; for (i=0; ihashsize; else if (krb5_cksumtypes_list[i].trunc_size) *length = krb5_cksumtypes_list[i].trunc_size; else *length = krb5_cksumtypes_list[i].hash->hashsize; return(0); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "hash_provider.h" #include "keyhash_provider.h" #include "cksumtypes.h" const struct krb5_cksumtypes krb5_cksumtypes_list[] = { { CKSUMTYPE_CRC32, KRB5_CKSUMFLAG_NOT_COLL_PROOF, "crc32", "CRC-32", 0, NULL, &krb5int_hash_crc32, 0, #ifdef _KERNEL NULL, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_DESCBC, 0, "des-cbc", "DES cbc mode", ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_descbc, 0, 0, #ifdef _KERNEL NULL, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_RSA_MD5, 0, "md5", "RSA-MD5", 0, NULL, &krb5int_hash_md5, 0, #ifdef _KERNEL SUN_CKM_MD5, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_RSA_MD5_DES, 0, "md5-des", "RSA-MD5 with DES cbc mode", ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md5des, 0, 0, #ifdef _KERNEL SUN_CKM_MD5, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_NIST_SHA, 0, "sha", "NIST-SHA", 0, NULL, &krb5int_hash_sha1, 0, #ifdef _KERNEL SUN_CKM_SHA1, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE, "hmac-sha1-des3", "HMAC-SHA1 DES3 key", 0, NULL, &krb5int_hash_sha1, 0, #ifdef _KERNEL SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE, "hmac-sha1-des3-kd", "HMAC-SHA1 DES3 key", /* alias */ 0, NULL, &krb5int_hash_sha1, 0, #ifdef _KERNEL SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, "hmac-md5-rc4", "Microsoft HMAC MD5 (RC4 key)", ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, NULL, 0, #ifdef _KERNEL SUN_CKM_MD5, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, "hmac-md5-enc", "Microsoft HMAC MD5 (RC4 key)", /*Heimdal alias*/ ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, NULL, 0, #ifdef _KERNEL SUN_CKM_MD5, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, "hmac-md5-earcfour", "Microsoft HMAC MD5 (RC4 key)", /* alias*/ ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, NULL, 0, #ifdef _KERNEL SUN_CKM_MD5, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_SHA1_96_AES128, KRB5_CKSUMFLAG_DERIVE, "hmac-sha1-96-aes128", "HMAC-SHA1 AES128 key", 0, NULL, &krb5int_hash_sha1, 12, #ifdef _KERNEL SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { CKSUMTYPE_HMAC_SHA1_96_AES256, KRB5_CKSUMFLAG_DERIVE, "hmac-sha1-96-aes256", "HMAC-SHA1 AES256 key", 0, NULL, &krb5int_hash_sha1, 12, #ifdef _KERNEL SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID #endif /* _KERNEL */ } }; const int krb5_cksumtypes_length = sizeof(krb5_cksumtypes_list)/sizeof(struct krb5_cksumtypes); /* Solaris Kerberos */ #ifdef _KERNEL void setup_kef_cksumtypes() { int i; struct krb5_cksumtypes *ck; for (i=0; imt_c_name != NULL && ck->kef_cksum_mt == CRYPTO_MECH_INVALID) { ck->kef_cksum_mt = crypto_mech2id(ck->mt_c_name); KRB5_LOG1(KRB5_INFO, "setup_kef_cksumtypes() - " "%s ==> %ld", ck->mt_c_name, (ulong_t)ck->kef_cksum_mt); } } } #endif /* _KERNEL */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the software, * derivative works or modified versions, and any portions thereof. * * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER * RESULTING FROM THE USE OF THIS SOFTWARE. * * Key combination function. * * If Key1 and Key2 are two keys to be combined, the algorithm to combine * them is as follows. * * Definitions: * * k-truncate is defined as truncating to the key size the input. * * DR is defined as the generate "random" data from a key * (defined in crypto draft) * * DK is defined as the key derivation function (krb5_derive_key()) * * (note: | means "concatenate") * * Combine key algorithm: * * R1 = DR(Key1, n-fold(Key2)) [ Output is length of Key1 ] * R2 = DR(Key2, n-fold(Key1)) [ Output is length of Key2 ] * * rnd = n-fold(R1 | R2) [ Note: output size of nfold must be appropriately * sized for random-to-key function ] * tkey = random-to-key(rnd) * Combine-Key(Key1, Key2) = DK(tkey, CombineConstant) * * CombineConstant is defined as the byte string: * * { 0x63 0x6f 0x6d 0x62 0x69 0x6e 0x65 }, which corresponds to the * ASCII encoding of the string "combine" */ #include "k5-int.h" #include "etypes.h" #include "dk.h" /* Solaris Kerberos */ static krb5_error_code dr (krb5_context context, const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, unsigned char *outdata, const krb5_data *in_constant); /* * We only support this combine_keys algorithm for des and 3des keys. * Everything else should use the PRF defined in the crypto framework. * We don't implement that yet. */ static krb5_boolean enctype_ok (krb5_enctype e) { switch (e) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES3_CBC_SHA1: return 1; default: return 0; } } krb5_error_code krb5int_c_combine_keys (krb5_context context, krb5_keyblock *key1, krb5_keyblock *key2, krb5_keyblock *outkey) { unsigned char *r1, *r2, *combined, *rnd, *output; size_t keybytes, keylength; const struct krb5_enc_provider *enc; krb5_data input, randbits; krb5_keyblock tkey; krb5_error_code ret; int i, myalloc = 0; if (!(enctype_ok(key1->enctype)&&enctype_ok(key2->enctype))) return (KRB5_CRYPTO_INTERNAL); if (key1->length != key2->length || key1->enctype != key2->enctype) return (KRB5_CRYPTO_INTERNAL); /* * Find our encryption algorithm */ for (i = 0; i < krb5_enctypes_length; i++) { if (krb5_enctypes_list[i].etype == key1->enctype) break; } if (i == krb5_enctypes_length) return (KRB5_BAD_ENCTYPE); enc = krb5_enctypes_list[i].enc; keybytes = enc->keybytes; keylength = enc->keylength; /* * Allocate and set up buffers */ if ((r1 = (unsigned char *) malloc(keybytes)) == NULL) return (ENOMEM); if ((r2 = (unsigned char *) malloc(keybytes)) == NULL) { free(r1); return (ENOMEM); } if ((rnd = (unsigned char *) malloc(keybytes)) == NULL) { free(r1); free(r2); return (ENOMEM); } if ((combined = (unsigned char *) malloc(keybytes * 2)) == NULL) { free(r1); free(r2); free(rnd); return (ENOMEM); } if ((output = (unsigned char *) malloc(keylength)) == NULL) { free(r1); free(r2); free(rnd); free(combined); return (ENOMEM); } /* * Get R1 and R2 (by running the input keys through the DR algorithm. * Note this is most of derive-key, but not all. */ input.length = key2->length; input.data = (char *) key2->contents; /* Solaris Kerberos */ if ((ret = dr(context, enc, key1, r1, &input))) goto cleanup; #if 0 { int i; printf("R1 ="); for (i = 0; i < keybytes; i++) printf(" %02x", (unsigned char) r1[i]); printf("\n"); } #endif input.length = key1->length; input.data = (char *) key1->contents; /* Solaris Kerberos */ if ((ret = dr(context, enc, key2, r2, &input))) goto cleanup; #if 0 { int i; printf("R2 ="); for (i = 0; i < keybytes; i++) printf(" %02x", (unsigned char) r2[i]); printf("\n"); } #endif /* * Concatenate the two keys together, and then run them through * n-fold to reduce them to a length appropriate for the random-to-key * operation. Note here that krb5_nfold() takes sizes in bits, hence * the multiply by 8. */ memcpy(combined, r1, keybytes); memcpy(combined + keybytes, r2, keybytes); krb5_nfold((keybytes * 2) * 8, combined, keybytes * 8, rnd); #if 0 { int i; printf("rnd ="); for (i = 0; i < keybytes; i++) printf(" %02x", (unsigned char) rnd[i]); printf("\n"); } #endif /* * Run the "random" bits through random-to-key to produce a encryption * key. */ randbits.length = keybytes; randbits.data = (char *) rnd; tkey.length = keylength; tkey.contents = output; /* Solaris Kerberos */ if ((ret = (*(enc->make_key))(context, &randbits, &tkey))) goto cleanup; #if 0 { int i; printf("tkey ="); for (i = 0; i < tkey.length; i++) printf(" %02x", (unsigned char) tkey.contents[i]); printf("\n"); } #endif /* * Run through derive-key one more time to produce the final key. * Note that the input to derive-key is the ASCII string "combine". */ input.length = 7; /* Note; change this if string length changes */ input.data = "combine"; /* * Just FYI: _if_ we have space here in the key, then simply use it * without modification. But if the key is blank (no allocated storage) * then allocate some memory for it. This allows programs to use one of * the existing keys as the output key, _or_ pass in a blank keyblock * for us to allocate. It's easier for us to allocate it since we already * know the crypto library internals */ if (outkey->length == 0 || outkey->contents == NULL) { outkey->contents = (krb5_octet *) malloc(keylength); if (!outkey->contents) { ret = ENOMEM; goto cleanup; } outkey->length = keylength; outkey->enctype = key1->enctype; myalloc = 1; } /* Solaris Kerberos */ if ((ret = krb5_derive_key(context, enc, &tkey, outkey, &input))) { if (myalloc) { free(outkey->contents); outkey->contents = NULL; } goto cleanup; } #if 0 { int i; printf("output ="); for (i = 0; i < outkey->length; i++) printf(" %02x", (unsigned char) outkey->contents[i]); printf("\n"); } #endif ret = 0; cleanup: memset(r1, 0, keybytes); memset(r2, 0, keybytes); memset(rnd, 0, keybytes); memset(combined, 0, keybytes * 2); memset(output, 0, keylength); free(r1); free(r2); free(rnd); free(combined); free(output); return (ret); } /* * Our DR function; mostly taken from derive.c */ /* Solaris Kerberos */ static krb5_error_code dr ( krb5_context context, const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, unsigned char *out, const krb5_data *in_constant) { size_t blocksize, keybytes, keylength, n; unsigned char *inblockdata, *outblockdata; krb5_data inblock, outblock; blocksize = enc->block_size; keybytes = enc->keybytes; keylength = enc->keylength; /* allocate and set up buffers */ if ((inblockdata = (unsigned char *) malloc(blocksize)) == NULL) return(ENOMEM); if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) { free(inblockdata); return(ENOMEM); } inblock.data = (char *) inblockdata; inblock.length = blocksize; outblock.data = (char *) outblockdata; outblock.length = blocksize; /* initialize the input block */ if (in_constant->length == inblock.length) { memcpy(inblock.data, in_constant->data, inblock.length); } else { krb5_nfold(in_constant->length*8, (unsigned char *) in_constant->data, inblock.length*8, (unsigned char *) inblock.data); } /* loop encrypting the blocks until enough key bytes are generated */ n = 0; while (n < keybytes) { /* Solaris Kerberos */ (*(enc->encrypt))(context, inkey, 0, &inblock, &outblock); if ((keybytes - n) <= outblock.length) { memcpy(out+n, outblock.data, (keybytes - n)); break; } memcpy(out+n, outblock.data, outblock.length); memcpy(inblock.data, outblock.data, outblock.length); n += outblock.length; } /* clean memory, free resources and exit */ memset(inblockdata, 0, blocksize); memset(outblockdata, 0, blocksize); free(outblockdata); free(inblockdata); return(0); } /* * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/crypto/crc32/crc.c * * Copyright 1990 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. 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. * * * CRC-32/AUTODIN-II routines */ #include #include #include #include static uint32_t const crc_table[256] = { CRC32_TABLE }; void mit_crc32(in, in_length, cksum) krb5_const krb5_pointer in; krb5_const size_t in_length; unsigned long *cksum; { unsigned int crc; CRC32(crc, in, in_length, 0, crc_table); *cksum = crc; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "etypes.h" /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_enc_data *input, krb5_data *output) { int i; krb5_error_code ret = 0; for (i=0; ienctype) break; } if (i == krb5_enctypes_length) return(KRB5_BAD_ENCTYPE); if ((input->enctype != ENCTYPE_UNKNOWN) && (krb5_enctypes_list[i].etype != input->enctype)) return(KRB5_BAD_ENCTYPE); /* Solaris Kerberos */ #ifdef _KERNEL context->kef_cipher_mt = krb5_enctypes_list[i].kef_cipher_mt; context->kef_hash_mt = krb5_enctypes_list[i].kef_hash_mt; if (key->kef_key.ck_data == NULL) ret = init_key_kef(context->kef_cipher_mt, (krb5_keyblock *)key); if (ret) return(ret); #else if ((ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key))) return (ret); #endif /* _KERNEL */ /* Solaris Kerberos */ return((*(krb5_enctypes_list[i].decrypt)) (context, krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, key, usage, ivec, &input->ciphertext, output)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 2001 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. * * Section 6 (Encryption) of the Kerberos revisions document defines * cipher states to be used to chain encryptions and decryptions * together. Examples of cipher states include initialization vectors * for CBC encription. Most Kerberos encryption systems can share * code for initializing and freeing cipher states. This file * contains that default code. */ #include "k5-int.h" /* ARGSUSED */ krb5_error_code krb5int_des_init_state (krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, krb5_data *new_state ) { new_state->length = 8; new_state->data = (void *) MALLOC(8); if (new_state->data) { /* Solaris Kerberos */ (void) memset (new_state->data, 0, new_state->length); /* We need to copy in the key for des-cbc-cr--ick, but that's how it works*/ if (key->enctype == ENCTYPE_DES_CBC_CRC) { /* Solaris Kerberos */ (void) memcpy (new_state->data, key->contents, new_state->length); } } else { return ENOMEM; } return 0; } /* ARGSUSED */ krb5_error_code krb5int_default_free_state (krb5_context context, krb5_data *state) { if (state->data) { FREE (state->data, state->length); state-> data = NULL; state->length = 0; } return 0; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 1995 by Richard P. Basch. All Rights Reserved. * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Richard P. Basch, * Lehman Brothers and M.I.T. make no representations about the suitability * of this software for any purpose. It is provided "as is" without * express or implied warranty. */ #include "des_int.h" /* * Triple-DES CBC encryption mode. */ #ifndef _KERNEL int mit_des3_cbc_encrypt(krb5_context context, const mit_des_cblock *in, mit_des_cblock *out, unsigned long length, krb5_keyblock *key, const mit_des_cblock ivec, int encrypt) { int ret = KRB5_PROG_ETYPE_NOSUPP; KRB5_MECH_TO_PKCS algos; CK_MECHANISM mechanism; CK_RV rv; /* For the Key Object */ ret = 0; if ((rv = get_algo(key->enctype, &algos)) != CKR_OK) { KRB5_LOG0(KRB5_ERR, "failure to get algo id in function " "mit_des3_cbc_encrypt."); ret = PKCS_ERR; goto cleanup; } rv = init_key_uef(krb_ctx_hSession(context), key); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "init_key_uef failed in " "mit_des3_cbc_encrypt: rv = 0x%0x", rv); ret = PKCS_ERR; goto cleanup; } mechanism.mechanism = algos.enc_algo; mechanism.pParameter = (void*)ivec; if (ivec != NULL) mechanism.ulParameterLen = sizeof(mit_des_cblock); else mechanism.ulParameterLen = 0; if (encrypt) rv = C_EncryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); else rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptInit/C_DecryptInit failed in " "mit_des3_cbc_encrypt: rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } if (encrypt) rv = C_Encrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in, (CK_ULONG)length, (CK_BYTE_PTR)out, (CK_ULONG_PTR)&length); else rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in, (CK_ULONG)length, (CK_BYTE_PTR)out, (CK_ULONG_PTR)&length); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_Encrypt/C_Decrypt failed in mit_des3_cbc_encrypt: " "rv = 0x%x", rv); ret = PKCS_ERR; } cleanup: if (ret) (void) memset(out, 0, length); KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() end ret=%d\n", ret); return(ret); } #else #include /* ARGSUSED */ int mit_des3_cbc_encrypt(krb5_context context, const mit_des_cblock *in, mit_des_cblock *out, unsigned long length, krb5_keyblock *key, const mit_des_cblock ivec, int encrypt) { int ret = KRB5_PROG_ETYPE_NOSUPP; krb5_data ivdata; KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() start encrypt=%d", encrypt); ivdata.data = (char *)ivec; ivdata.length = sizeof(mit_des_cblock); ret = k5_ef_crypto((const char *)in, (char *)out, length, key, &ivdata, encrypt); KRB5_LOG(KRB5_INFO, "mit_des3_cbc_encrypt() end retval=%d", ret); return(ret); } #endif /* !_KERNEL */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include int k5_ef_crypto(const char *in, char *out, long length, krb5_keyblock *key, const krb5_data *ivec, int encrypt_flag) { int rv = CRYPTO_FAILED; crypto_mechanism_t mech; crypto_data_t d1, d2; ASSERT(in != NULL); ASSERT(out != NULL); ASSERT(key != NULL); ASSERT(key->contents != NULL); bzero(&d1, sizeof (d1)); bzero(&d2, sizeof (d2)); d1.cd_format = CRYPTO_DATA_RAW; d1.cd_offset = 0; d1.cd_length = length; d1.cd_raw.iov_base = (char *)in; d1.cd_raw.iov_len = length; d2.cd_format = CRYPTO_DATA_RAW; d2.cd_offset = 0; d2.cd_length = length; d2.cd_raw.iov_base = (char *)out; d2.cd_raw.iov_len = length; mech.cm_type = key->kef_mt; if (mech.cm_type == CRYPTO_MECH_INVALID) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto - invalid crypto mech type: 0x%llx", (long long)key->kef_mt); return (CRYPTO_FAILED); } if (ivec != NULL) { mech.cm_param_len = ivec->length; mech.cm_param = (char *)ivec->data; } else { mech.cm_param_len = 0; mech.cm_param = NULL; } if (encrypt_flag) rv = crypto_encrypt(&mech, &d1, &key->kef_key, key->key_tmpl, (in != out ? &d2 : NULL), NULL); else rv = crypto_decrypt(&mech, &d1, &key->kef_key, key->key_tmpl, (in != out ? &d2 : NULL), NULL); if (rv != CRYPTO_SUCCESS) { KRB5_LOG1(KRB5_ERR, "k5_ef_crypto: %s error: rv = 0x%08x", (encrypt_flag ? "encrypt" : "decrypt"), rv); return (CRYPTO_FAILED); } return (0); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1990 Dennis Ferguson. All rights reserved. * * Commercial use is permitted only if products which are derived from * or include this software are made available for purchase and/or use * in Canada. Otherwise, redistribution and use in source and binary * forms are permitted. */ /* * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode */ #include "des_int.h" /* * des_cbc_encrypt - {en,de}crypt a stream in CBC mode */ /* SUNW14resync - sparcv9 cc complained about lack of object init */ /* = all zero */ const mit_des_cblock mit_des_zeroblock = {0, 0, 0, 0, 0, 0, 0, 0}; #undef mit_des_cbc_encrypt #ifndef _KERNEL int mit_des_cbc_encrypt(context, in, out, length, key, ivec, encrypt) krb5_context context; const mit_des_cblock *in; mit_des_cblock *out; long length; krb5_keyblock *key; mit_des_cblock ivec; int encrypt; { krb5_error_code ret = KRB5_PROG_ETYPE_NOSUPP; KRB5_MECH_TO_PKCS algos; CK_MECHANISM mechanism; CK_RV rv; /* For the Key Object */ ret = 0; if ((rv = get_algo(key->enctype, &algos)) != CKR_OK) { KRB5_LOG0(KRB5_ERR, "failure to get algo id in function " "mit_des_cbc_encrypt."); ret = PKCS_ERR; goto cleanup; } rv = init_key_uef(krb_ctx_hSession(context), key); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "init_key_uef failed in " "mit_des_cbc_encrypt: rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } mechanism.mechanism = algos.enc_algo; mechanism.pParameter = ivec; if (ivec != NULL) mechanism.ulParameterLen = MIT_DES_BLOCK_LENGTH; else mechanism.ulParameterLen = 0; if (encrypt) rv = C_EncryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); else rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptInit/C_DecryptInit failed in " "mit_des_cbc_encrypt: rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } if (encrypt) rv = C_Encrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in, (CK_ULONG)length, (CK_BYTE_PTR)out, (CK_ULONG_PTR)&length); else rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)in, (CK_ULONG)length, (CK_BYTE_PTR)out, (CK_ULONG_PTR)&length); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_Encrypt/C_Decrypt failed in mit_des_cbc_encrypt: " "rv = 0x%x", rv); ret = PKCS_ERR; } cleanup: if (ret) (void) memset(out, 0, length); KRB5_LOG(KRB5_INFO, "mit_des_cbc_encrypt() end retval=%d", ret); return(ret); } #else /* * This routine performs DES cipher-block-chaining operation, either * encrypting from cleartext to ciphertext, if encrypt != 0 or * decrypting from ciphertext to cleartext, if encrypt == 0. * * The key schedule is passed as an arg, as well as the cleartext or * ciphertext. The cleartext and ciphertext should be in host order. * * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not * enough space was provided, your program will get trashed. * * For encryption, the cleartext string is null padded, at the end, to * an integral multiple of eight bytes. * * For decryption, the ciphertext will be used in integral multiples * of 8 bytes, but only the first "length" bytes returned into the * cleartext. */ /* ARGSUSED */ int mit_des_cbc_encrypt(krb5_context context, const mit_des_cblock *in, mit_des_cblock *out, long length, krb5_keyblock *key, mit_des_cblock ivec, int encrypt) { int ret = KRB5_PROG_ETYPE_NOSUPP; krb5_data ivdata; ret = 0; KRB5_LOG(KRB5_INFO, "mit_des_cbc_encrypt() start encrypt=%d", encrypt); ivdata.data = (char *)ivec; ivdata.length = sizeof(mit_des_cblock); ret = k5_ef_crypto((const char *)in, (char *)out, length, key, &ivdata, encrypt); KRB5_LOG(KRB5_INFO, "mit_des_cbc_encrypt() end retval=%d", ret); return(ret); } #endif /* !_KERNEL */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode */ #include "des_int.h" /* * This routine performs DES cipher-block-chaining checksum operation, * a.k.a. Message Authentication Code. It ALWAYS encrypts from input * to a single 64 bit output MAC checksum. * * The key schedule is passed as an arg, as well as the cleartext or * ciphertext. The cleartext and ciphertext should be in host order. * * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was * provided, your program will get trashed. * * The input is null padded, at the end (highest addr), to an integral * multiple of eight bytes. */ unsigned long mit_des_cbc_cksum(krb5_context context, const krb5_octet *in, krb5_octet *out, unsigned long length, krb5_keyblock *key, const krb5_octet *ivec) { krb5_error_code ret = 0; krb5_data input; krb5_data output; krb5_data ivecdata; input.data = (char *)in; input.length = length; output.data = (char *)out; output.length = MIT_DES_BLOCK_LENGTH; ivecdata.data = (char *)ivec; ivecdata.length = MIT_DES_BLOCK_LENGTH; ret = k5_ef_mac(context, key, &ivecdata, (const krb5_data *)&input, &output); return (ret); } /* * These routines check and fix parity of encryption keys for the DES * algorithm. * * They are a replacement for routines in key_parity.c, that don't require * the table building that they do. * * Mark Eichin -- Cygnus Support */ #include "des_int.h" /* * des_fixup_key_parity: Forces odd parity per byte; parity is bits * 8,16,...64 in des order, implies 0, 8, 16, ... * vax order. */ #define smask(step) ((1<>step)&smask(step))) #define parity_char(x) pstep(pstep(pstep((x),4),2),1) void mit_des_fixup_key_parity(mit_des_cblock key) { int i; for (i=0; ilength); if (*outkey == NULL) return (ENOMEM); constantdata[0] = (usage>>24)&0xff; constantdata[1] = (usage>>16)&0xff; constantdata[2] = (usage>>8)&0xff; constantdata[3] = usage&0xff; constantdata[4] = DK_CKSUM_KEY_BYTE; d1.data = (char *)constantdata; d1.length = sizeof(constantdata); ret = krb5_derive_key(context, enc, key, *outkey, &d1); if (ret) { krb5_free_keyblock(context, *outkey); *outkey = NULL; return (ret); } #ifdef _KERNEL /* * By default, derived keys get the "mech_type" * that was associated with their parent. * we need to switch the mech_type to correspond * to the checksum mech type. */ if (ret == 0 && (*outkey)->kef_mt != context->kef_cksum_mt) { (*outkey)->kef_mt = context->kef_cksum_mt; if ((*outkey)->key_tmpl != NULL) { crypto_destroy_ctx_template((*outkey)->key_tmpl); (*outkey)->key_tmpl = NULL; } ret = update_key_template(*outkey); } #endif /* _KERNEL */ if (ret == 0) ret = add_derived_key((krb5_keyblock *)key, usage, DK_CKSUM_KEY_BYTE, *outkey); } KRB5_LOG0(KRB5_INFO, "derive_cksum_key() end."); return (ret); } /* ARGSUSED */ krb5_error_code krb5_dk_make_checksum(context, hash, key, usage, input, output) krb5_context context; krb5_const struct krb5_hash_provider *hash; krb5_const krb5_keyblock *key; krb5_keyusage usage; krb5_const krb5_data *input; krb5_data *output; { int i; krb5_error_code ret; krb5_keyblock *cksum_key = NULL; struct krb5_enc_provider *enc = NULL; KRB5_LOG0(KRB5_INFO, "krb5_dk_make_checksum() start"); for (i=0; ienctype) break; } if (i == krb5_enctypes_length) { KRB5_LOG(KRB5_ERR, "krb5_ck_make_checksum bad enctype: %d", key->enctype); return(KRB5_BAD_ENCTYPE); } enc = (struct krb5_enc_provider *)krb5_enctypes_list[i].enc; #ifdef _KERNEL if (key->kef_key.ck_data == NULL && (ret = init_key_kef(krb5_enctypes_list[i].kef_cipher_mt, (krb5_keyblock *)key))) goto cleanup; #endif ret = derive_cksum_key(context, enc, key, usage, &cksum_key); if (ret != 0) goto cleanup; #ifdef _KERNEL if ((ret = krb5_hmac(context, (krb5_keyblock *)cksum_key, input, output))) { KRB5_LOG(KRB5_ERR, "krb5_hmac error: %0x", ret); (void) memset(output->data, 0, output->length); } #else if ((ret = krb5_hmac(context, hash, cksum_key, 1, input, output)) != 0) { KRB5_LOG(KRB5_ERR, "krb5_hmac error: %0x", ret); (void) memset(output->data, 0, output->length); } #endif /* _KERNEL */ cleanup: KRB5_LOG0(KRB5_INFO, "krb5_dk_make_checksum() end"); return(ret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "dk.h" #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ /* * Search for a derived key based on the input key, * the usage constant and the dkid byte. * * Return *derived key on success, NULL on failure. */ krb5_keyblock * find_derived_key(krb5_keyusage usage, uchar_t dkid, krb5_keyblock *key) { krb5_dk_node *dknode = key->dk_list; while (dknode != NULL) { if (usage == dknode->usage && dkid == dknode->dkid) { KRB5_LOG1(KRB5_INFO, "find_derived_key - MATCH FOUND %d 0x%0x", usage, dkid); return(dknode->derived_key); } dknode = dknode->next; } KRB5_LOG0(KRB5_INFO, "find_derived_key - no match"); return(NULL); } /* * Add a derived key to the dk_list for the indicated key. */ krb5_error_code add_derived_key(krb5_keyblock *key, krb5_keyusage usage, uchar_t dkid, krb5_keyblock *derived_key) { krb5_dk_node *dknode; KRB5_LOG1(KRB5_INFO, "add_derived_key: %d 0x%0x", usage, dkid); if (key->dk_list == NULL) { key->dk_list = MALLOC(sizeof(krb5_dk_node)); if (key->dk_list == NULL) return (ENOMEM); dknode = key->dk_list; } else { dknode = key->dk_list; /* * Find last derived key in list */ while (dknode->next != NULL) dknode = dknode->next; dknode->next = MALLOC(sizeof(krb5_dk_node)); if (dknode->next == NULL) return (ENOMEM); dknode = dknode->next; } dknode->usage = usage; dknode->dkid = dkid; dknode->derived_key = derived_key; dknode->next = NULL; return (0); } /* * Utility function to create a new keyblock * Return NULL on failure. */ krb5_keyblock * krb5_create_derived_keyblock(int keysize) { krb5_keyblock *key = MALLOC(sizeof(krb5_keyblock)); KRB5_LOG0(KRB5_INFO, "krb5_create_derived_keyblock()"); if (key == NULL) return (NULL); bzero(key, sizeof(krb5_keyblock)); key->length = keysize; key->contents = (uchar_t *)MALLOC(key->length); if (key->contents == NULL) { FREE(key, sizeof(krb5_keyblock)); return (NULL); } bzero(key->contents, key->length); #ifdef _KERNEL key->kef_mt = CRYPTO_MECH_INVALID; key->key_tmpl = NULL; #else key->hKey = CK_INVALID_HANDLE; #endif /* _KERNEL */ return(key); } /* * initialize the derived key values in the context. */ krb5_error_code init_derived_keydata(krb5_context context, const struct krb5_enc_provider *enc, krb5_keyblock *key, krb5_keyusage usage, krb5_keyblock **d_encr_key, krb5_keyblock **d_hmac_key) { krb5_error_code rv = 0; unsigned char constantdata[K5CLENGTH]; krb5_keyblock *cached_key; krb5_data d1; KRB5_LOG0(KRB5_INFO,"init_ef_derived_keydata()."); /* * Get a derived encryption key, either from the cache * or by calculation. */ cached_key = find_derived_key(usage, DK_ENCR_KEY_BYTE, key); if (cached_key != NULL) *d_encr_key = cached_key; else { *d_encr_key = krb5_create_derived_keyblock(key->length); if (*d_encr_key == NULL) { return (ENOMEM); } (*d_encr_key)->enctype = key->enctype; constantdata[0] = (usage>>24)&0xff; constantdata[1] = (usage>>16)&0xff; constantdata[2] = (usage>>8)&0xff; constantdata[3] = usage&0xff; constantdata[4] = DK_ENCR_KEY_BYTE; d1.data = (char *)constantdata; d1.length = sizeof(constantdata); rv = krb5_derive_key(context, enc, key, *d_encr_key, &d1); if (rv != 0) { krb5_free_keyblock(context, *d_encr_key); *d_encr_key = NULL; return (rv); } rv = add_derived_key(key, usage, DK_ENCR_KEY_BYTE, *d_encr_key); if (rv != 0) { krb5_free_keyblock(context, *d_encr_key); *d_encr_key = NULL; return (rv); } } /* * Get a derived HMAC key, either from the cache * or by calculation. */ cached_key = find_derived_key(usage, DK_HASH_KEY_BYTE, key); if (cached_key != NULL) *d_hmac_key = cached_key; else { *d_hmac_key = krb5_create_derived_keyblock(key->length); if (*d_hmac_key == NULL) { return (ENOMEM); } (*d_hmac_key)->enctype = key->enctype; constantdata[0] = (usage>>24)&0xff; constantdata[1] = (usage>>16)&0xff; constantdata[2] = (usage>>8)&0xff; constantdata[3] = usage&0xff; constantdata[4] = DK_HASH_KEY_BYTE; d1.data = (char *)constantdata; d1.length = sizeof(constantdata); rv = krb5_derive_key(context, enc, key, *d_hmac_key, &d1); if (rv != 0) { krb5_free_keyblock(context, *d_hmac_key); *d_hmac_key = NULL; return (rv); } #ifdef _KERNEL /* * By default, derived keys get the "mech_type" * that was associated with their parent. * we need to switch the mech type of the derived HMAC key * to correspond to the mech type for the hmac key. */ if ((*d_hmac_key)->kef_mt != context->kef_hash_mt) { (*d_hmac_key)->kef_mt = context->kef_hash_mt; if ((*d_hmac_key)->key_tmpl != NULL) { crypto_destroy_ctx_template((*d_hmac_key)->key_tmpl); (*d_hmac_key)->key_tmpl = NULL; } rv = update_key_template(*d_hmac_key); if (rv != 0) { krb5_free_keyblock(context, *d_hmac_key); *d_hmac_key = NULL; return (rv); } } #endif /* _KERNEL */ if (rv == 0) { rv = add_derived_key(key, usage, DK_HASH_KEY_BYTE, *d_hmac_key); if (rv != 0) { krb5_free_keyblock(context, *d_hmac_key); *d_hmac_key = NULL; return (rv); } } } KRB5_LOG0(KRB5_INFO,"init_ef_derived_keydata() end."); return (rv); } krb5_error_code krb5_derive_key(context, enc, inkey, outkey, in_constant) krb5_context context; krb5_const struct krb5_enc_provider *enc; krb5_const krb5_keyblock *inkey; krb5_keyblock *outkey; krb5_const krb5_data *in_constant; { size_t blocksize, keybytes, keylength, n; unsigned char *inblockdata, *outblockdata, *rawkey; krb5_data inblock, outblock; krb5_error_code ret = 0; KRB5_LOG0(KRB5_INFO, "krb5_derive_key() start"); blocksize = enc->block_size; keybytes = enc->keybytes; keylength = enc->keylength; if ((inkey->length != keylength) || (outkey->length != keylength)) return(KRB5_CRYPTO_INTERNAL); /* allocate and set up buffers */ if ((inblockdata = (unsigned char *) MALLOC(blocksize)) == NULL) return(ENOMEM); if ((outblockdata = (unsigned char *) MALLOC(blocksize)) == NULL) { FREE(inblockdata, blocksize); return(ENOMEM); } if ((rawkey = (unsigned char *) MALLOC(keybytes)) == NULL) { FREE(outblockdata, blocksize); FREE(inblockdata, blocksize); return(ENOMEM); } inblock.data = (char *) inblockdata; inblock.length = blocksize; outblock.data = (char *) outblockdata; outblock.length = blocksize; /* initialize the input block */ if (in_constant->length == inblock.length) { (void) memcpy(inblock.data, in_constant->data, inblock.length); } else { krb5_nfold(in_constant->length*8, (krb5_const unsigned char *) in_constant->data, inblock.length*8, (unsigned char *) inblock.data); } /* loop encrypting the blocks until enough key bytes are generated */ n = 0; while (n < keybytes) { ret = (*(enc->encrypt))(context, inkey, 0, &inblock, &outblock); if (ret) { KRB5_LOG(KRB5_INFO, "krb5_derive_key() encrypt error: %d", ret); goto cleanup; } if ((keybytes - n) <= outblock.length) { (void) memcpy(rawkey+n, outblock.data, (keybytes - n)); break; } (void) memcpy(rawkey+n, outblock.data, outblock.length); (void) memcpy(inblock.data, outblock.data, outblock.length); n += outblock.length; } /* postprocess the key */ inblock.data = (char *) rawkey; inblock.length = keybytes; outkey->enctype = inkey->enctype; ret = (*(enc->make_key))(context, &inblock, outkey); /* clean memory, free resources and exit */ cleanup: (void) memset(inblockdata, 0, blocksize); (void) memset(outblockdata, 0, blocksize); (void) memset(rawkey, 0, keybytes); FREE(rawkey, keybytes); FREE(outblockdata, blocksize); FREE(inblockdata, blocksize); KRB5_LOG0(KRB5_INFO, "krb5_derive_key() end"); return(ret); } /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "dk.h" #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ static krb5_error_code krb5_dk_decrypt_maybe_trunc_hmac(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output, size_t hmacsize); krb5_error_code krb5_dk_decrypt( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { return krb5_dk_decrypt_maybe_trunc_hmac(context, enc, hash, key, usage, ivec, input, output, 0); } krb5_error_code krb5int_aes_dk_decrypt( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { return krb5_dk_decrypt_maybe_trunc_hmac(context, enc, hash, key, usage, ivec, input, output, 96 / 8); } static krb5_error_code krb5_dk_decrypt_maybe_trunc_hmac( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output, size_t hmacsize) { krb5_error_code ret; size_t hashsize, blocksize, enclen, plainlen; unsigned char *plaindata = NULL, *cksum = NULL, *cn; krb5_data d1, d2; krb5_keyblock *derived_encr_key = NULL; krb5_keyblock *derived_hmac_key = NULL; KRB5_LOG0(KRB5_INFO, "krb5_dk_decrypt() start\n"); /* * Derive the encryption and hmac keys. * This routine is optimized to fetch the DK * from the original key's DK list. */ ret = init_derived_keydata(context, enc, (krb5_keyblock *)key, usage, &derived_encr_key, &derived_hmac_key); if (ret) return (ret); hashsize = hash->hashsize; blocksize = enc->block_size; if (hmacsize == 0) hmacsize = hashsize; else if (hmacsize > hashsize) return (KRB5KRB_AP_ERR_BAD_INTEGRITY); /* Verify input and output lengths. */ if (input->length < blocksize + hmacsize) return KRB5_BAD_MSIZE; if (output->length < input->length - blocksize - hmacsize) return KRB5_BAD_MSIZE; enclen = input->length - hmacsize; if ((plaindata = (unsigned char *) MALLOC(enclen)) == NULL) { ret = ENOMEM; goto cleanup; } /* decrypt the ciphertext */ d1.length = enclen; d1.data = input->data; d2.length = enclen; d2.data = (char *) plaindata; if ((ret = ((*(enc->decrypt))(context, derived_encr_key, ivec, &d1, &d2))) != 0) goto cleanup; if (ivec != NULL && ivec->length == blocksize) { cn = (unsigned char *) d1.data + d1.length - blocksize; } else { cn = NULL; } /* verify the hash */ if ((cksum = (unsigned char *) MALLOC(hashsize)) == NULL) { ret = ENOMEM; goto cleanup; } d1.length = hashsize; d1.data = (char *) cksum; #ifdef _KERNEL if ((ret = krb5_hmac(context, derived_hmac_key, &d2, &d1)) != 0) goto cleanup; #else if ((ret = krb5_hmac(context, hash, derived_hmac_key, 1, &d2, &d1)) != 0) goto cleanup; #endif /* _KERNEL */ if (memcmp(cksum, input->data+enclen, hmacsize) != 0) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto cleanup; } /* because this encoding isn't self-describing wrt length, the best we can do here is to compute the length minus the confounder. */ plainlen = enclen - blocksize; if (output->length < plainlen) { ret = KRB5_BAD_MSIZE; goto cleanup; } output->length = plainlen; (void) memcpy(output->data, d2.data+blocksize, output->length); /* * AES crypto updates the ivec differently, it is handled * in the AES crypto routines directly. */ if (cn != NULL && key->enctype != ENCTYPE_AES128_CTS_HMAC_SHA1_96 && key->enctype != ENCTYPE_AES256_CTS_HMAC_SHA1_96) { (void) memcpy(ivec->data, cn, blocksize); } ret = 0; cleanup: if (plaindata) { (void) memset(plaindata, 0, enclen); FREE(plaindata, enclen); } if (cksum) { (void) memset(cksum, 0, hashsize); FREE(cksum, hashsize); } KRB5_LOG(KRB5_INFO, "krb5_dk_decrypt() end, ret=%d\n", ret); return(ret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "dk.h" #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ /* the spec says that the confounder size and padding are specific to the encryption algorithm. This code (dk_encrypt_length and dk_encrypt) assume the confounder is always the blocksize, and the padding is always zero bytes up to the blocksize. If these assumptions ever fails, the keytype table should be extended to include these bits of info. */ void krb5_dk_encrypt_length(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t inputlen, size_t *length) { size_t blocksize, hashsize; blocksize = enc->block_size; hashsize = hash->hashsize; *length = krb5_roundup(blocksize+inputlen, blocksize) + hashsize; } krb5_error_code krb5_dk_encrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { size_t blocksize, plainlen, enclen; krb5_error_code ret; krb5_data d1, d2; unsigned char *plaintext = NULL, *cn; krb5_keyblock *derived_encr_key = NULL; krb5_keyblock *derived_hmac_key = NULL; KRB5_LOG0(KRB5_INFO, "krb5_dk_encrypt() start"); /* * Derive the encryption and hmac keys. * This routine is optimized to fetch the DK * from the original key's DK list. */ ret = init_derived_keydata(context, enc, (krb5_keyblock *)key, usage, &derived_encr_key, &derived_hmac_key); if (ret) return (ret); blocksize = enc->block_size; plainlen = krb5_roundup(blocksize+input->length, blocksize); krb5_dk_encrypt_length(enc, hash, input->length, &enclen); if (output->length < enclen) return(KRB5_BAD_MSIZE); if ((plaintext = (unsigned char *) MALLOC(plainlen)) == NULL) { return(ENOMEM); } /* put together the plaintext */ d1.length = blocksize; d1.data = (char *) plaintext; if ((ret = krb5_c_random_make_octets(context, &d1))) goto cleanup; (void) memcpy(plaintext+blocksize, input->data, input->length); (void) memset(plaintext+blocksize+input->length, 0, plainlen - (blocksize+input->length)); /* encrypt the plaintext */ d1.length = plainlen; d1.data = (char *) plaintext; d2.length = plainlen; d2.data = output->data; /* * Always use the derived encryption key here. */ if ((ret = ((*(enc->encrypt))(context, derived_encr_key, ivec, &d1, &d2)))) goto cleanup; if (ivec != NULL && ivec->length == blocksize) cn = (unsigned char *) d2.data + d2.length - blocksize; else cn = NULL; /* hash the plaintext */ d2.length = enclen - plainlen; d2.data = output->data+plainlen; output->length = enclen; #ifdef _KERNEL if ((ret = krb5_hmac(context, derived_hmac_key, &d1, &d2))) { (void) memset(d2.data, 0, d2.length); goto cleanup; } #else if ((ret = krb5_hmac(context, hash, derived_hmac_key, 1, &d1, &d2))) { (void) memset(d2.data, 0, d2.length); goto cleanup; } #endif /* _KERNEL */ /* update ivec */ if (cn != NULL) (void) memcpy(ivec->data, cn, blocksize); /* ret is set correctly by the prior call */ cleanup: FREE(plaintext, plainlen); KRB5_LOG(KRB5_INFO, "krb5_dk_encrypt() end, ret=%d\n", ret); return(ret); } /* Not necessarily "AES", per se, but "a CBC+CTS mode block cipher with a 96-bit truncated HMAC". */ /*ARGSUSED*/ void krb5int_aes_encrypt_length(enc, hash, inputlen, length) const struct krb5_enc_provider *enc; const struct krb5_hash_provider *hash; size_t inputlen; size_t *length; { size_t blocksize, hashsize; blocksize = enc->block_size; hashsize = 96 / 8; /* No roundup, since CTS requires no padding once we've hit the block size. */ *length = blocksize+inputlen + hashsize; } /*ARGSUSED*/ static krb5_error_code trunc_hmac (krb5_context context, const struct krb5_hash_provider *hash, const krb5_keyblock *ki, int num, const krb5_data *input, krb5_data *output) { size_t hashsize; krb5_error_code ret; char buff[256]; /* sufficiently large enough to hold current hmacs */ krb5_data tmphash; hashsize = hash->hashsize; if (hashsize < output->length) return (KRB5_CRYPTO_INTERNAL); tmphash.length = hashsize; tmphash.data = buff; #ifdef _KERNEL ret = krb5_hmac(context, ki, input, &tmphash); #else ret = krb5_hmac(context, hash, ki, num, input, &tmphash); #endif /* _KERNEL */ if (ret) (void) memset(output->data, 0, output->length); else /* truncate the HMAC output accordingly */ (void) memcpy(output->data, tmphash.data, output->length); (void) memset(buff, 0, sizeof(buff)); return (ret); } krb5_error_code krb5int_aes_dk_encrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { size_t blocksize, plainlen, enclen; krb5_error_code ret; krb5_data d1, d2; unsigned char *plaintext, *cn; krb5_keyblock *derived_encr_key = NULL; krb5_keyblock *derived_hmac_key = NULL; /* * Derive the encryption and hmac keys. * This routine is optimized to fetch the DK * from the original key's DK list. */ ret = init_derived_keydata(context, enc, (krb5_keyblock *)key, usage, &derived_encr_key, &derived_hmac_key); if (ret) return (ret); blocksize = enc->block_size; plainlen = blocksize+input->length; krb5int_aes_encrypt_length(enc, hash, input->length, &enclen); /* key->length, ivec will be tested in enc->encrypt */ if (output->length < enclen) return(KRB5_BAD_MSIZE); if ((plaintext = (unsigned char *) MALLOC(plainlen)) == NULL) { return(ENOMEM); } d1.length = blocksize; d1.data = (char *)plaintext; if ((ret = krb5_c_random_make_octets(context, &d1))) goto cleanup; (void) memcpy(plaintext+blocksize, input->data, input->length); /* Ciphertext stealing; there should be no more. */ if (plainlen != blocksize + input->length) { ret = KRB5_BAD_KEYSIZE; goto cleanup; } /* encrypt the plaintext */ d1.length = plainlen; d1.data = (char *)plaintext; d2.length = plainlen; d2.data = output->data; if ((ret = ((*(enc->encrypt))(context, derived_encr_key, ivec, &d1, &d2)))) goto cleanup; if (ivec != NULL && ivec->length == blocksize) { int nblocks = (d2.length + blocksize - 1) / blocksize; cn = (uchar_t *) d2.data + blocksize * (nblocks - 2); } else { cn = NULL; } /* hash the plaintext */ d2.length = enclen - plainlen; d2.data = output->data+plainlen; if (d2.length != 96 / 8) goto cleanup; if ((ret = trunc_hmac(context, hash, derived_hmac_key, 1, &d1, &d2))) { (void) memset(d2.data, 0, d2.length); goto cleanup; } output->length = enclen; /* update ivec */ if (cn != NULL) { (void) memcpy(ivec->data, cn, blocksize); } /* ret is set correctly by the prior call */ cleanup: (void) memset(plaintext, 0, plainlen); FREE(plaintext, plainlen); return(ret); } /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Note, this file is cstyle and lint clean and should stay that way. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #include #include #define BLOCK_SIZE 16 /* * AES encrypt using CipherText Stealing mode built on top of CBC mode. CBC is * being used because the Solaris Cryptographic Framework/PKCS11 does not * currently support CTS while CBC is supported. CBC as compared to ECB that * was previously used allows crypto providers to do the crypto more * efficiently. In addition there is a crypto card (SCA6000) that did not * provide ECB mode so krb was unable to take advantage. If CTS mode is ever * supported by the Solaris Cryptographic Framework then this code should be * changed to use that. * * CTS is based on what is described in Schneier's Applied Cryptography and RFC * 3962. */ #ifdef _KERNEL /*ARGSUSED*/ krb5_error_code krb5int_aes_encrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0; int nblocks, partialamount; crypto_mechanism_t mech; /* * nlobp = next to last output block pointer, lobp = last output block * pointer */ char *nlobp, *lobp; char local_iv_data[BLOCK_SIZE]; krb5_data local_iv; KRB5_LOG0(KRB5_INFO, "In krb5int_aes_encrypt(kernel): start"); ASSERT(input != NULL); if (input->length < BLOCK_SIZE) return (KRB5_BAD_MSIZE); ASSERT(output != NULL); ASSERT(input->length == output->length); ASSERT(key != NULL); ASSERT(key->key_tmpl != NULL); ASSERT(key->kef_mt == crypto_mech2id(SUN_CKM_AES_CBC)); if (ivec != NULL) { /* * This function updates ivec->data if the ivec is passed in so * it better have a data pointer and a proper length. */ if (ivec->data == NULL || ivec->length != BLOCK_SIZE) { ASSERT(ivec->data != NULL); ASSERT(ivec->length == BLOCK_SIZE); KRB5_LOG1(KRB5_ERR, "In krb5int_aes_encrypt: error " "ivec->data = %p ivec->length = %d", (void *)ivec->data, ivec->length); ret = KRB5_CRYPTO_INTERNAL; goto cleanup; } } /* number of input blocks including partial block */ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks); /* get # of bytes in partially filled block */ partialamount = input->length % BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount); if (nblocks == 1 || (partialamount == 0)) { /* * Simple case: * * Use CBC for all plaintext blocks, all must be full, then swap * last 2 ciphertext blocks to implement CTS. Note, CBC needs a * non-NULL IV. */ if (ivec != NULL) { local_iv.data = ivec->data; local_iv.length = ivec->length; } else { bzero(local_iv_data, sizeof (local_iv_data)); local_iv.data = local_iv_data; local_iv.length = sizeof (local_iv_data); } /* Note using TRUE here because encryption is desired */ ret = k5_ef_crypto((const char *)input->data, (char *)output->data, input->length, (krb5_keyblock *)key, &local_iv, TRUE); if (ret != 0) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto: error: ret = 0x%08x", ret); goto cleanup; } if (nblocks > 1) { /* * swap last 2 ciphertext blocks to implement CTS */ char tmp[BLOCK_SIZE]; nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE)); lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE)); bcopy(nlobp, tmp, BLOCK_SIZE); bcopy(lobp, nlobp, BLOCK_SIZE); bcopy(tmp, lobp, BLOCK_SIZE); } } else { /* * Complex case: * * This implements CTS mode where there is > 1 block and the * last block is partially filled Uses CBC mode in the kCF, then * does some swapping. * * pt = plain text, ct = cipher text */ char tmp_pt[BLOCK_SIZE], tmp_ct[BLOCK_SIZE]; /* Note the iovec below is NOT the ivec in the crypto sense */ struct iovec iovarray_pt[2], iovarray_ct[2]; struct uio uio_pt, uio_ct; /* ct = ciphertext, pt = plaintext */ crypto_data_t ct, pt; /* tmp_pt will provide 0 padding for last parital pt block */ bzero(tmp_pt, sizeof (tmp_pt)); /* * Setup the uio/iovecs so only one call to crypto_encrypt() is * made. Plaintext first. */ pt.cd_format = CRYPTO_DATA_UIO; pt.cd_offset = 0; pt.cd_length = nblocks * BLOCK_SIZE; pt.cd_miscdata = NULL; bzero(&uio_pt, sizeof (uio_pt)); pt.cd_uio = &uio_pt; pt.cd_uio->uio_iov = iovarray_pt; pt.cd_uio->uio_iovcnt = 2; pt.cd_uio->uio_segflg = UIO_SYSSPACE; /* * first iovec has all full blocks of pt. */ pt.cd_uio->uio_iov[0].iov_base = (char *)input->data; /* use full block input */ pt.cd_uio->uio_iov[0].iov_len = input->length - partialamount; KRB5_LOG(KRB5_INFO, "pt0 iov_len = %d", (int)pt.cd_uio->uio_iov[0].iov_len); /* * second iovec has the parital pt and 0 padding */ pt.cd_uio->uio_iov[1].iov_base = tmp_pt; /* * since the first iovec includes the last partial pt, * set length to enough bytes to pad out to a full block */ bcopy(input->data + (input->length - partialamount), tmp_pt, partialamount); pt.cd_uio->uio_iov[1].iov_len = BLOCK_SIZE; /* setup ciphertext iovecs */ ct.cd_format = CRYPTO_DATA_UIO; ct.cd_offset = 0; ct.cd_length = nblocks * BLOCK_SIZE; ct.cd_miscdata = NULL; bzero(&uio_ct, sizeof (uio_ct)); ct.cd_uio = &uio_ct; ct.cd_uio->uio_iov = iovarray_ct; ct.cd_uio->uio_iovcnt = 2; ct.cd_uio->uio_segflg = UIO_SYSSPACE; /* * First iovec has almost all the ct but not the ct for the last * partial pt with the padding. That will be stored in the * secont ct iovec. */ ct.cd_uio->uio_iov[0].iov_base = (char *)output->data; ct.cd_uio->uio_iov[0].iov_len = output->length - partialamount; KRB5_LOG(KRB5_INFO, "ct0 iov_len = %d", (int)ct.cd_uio->uio_iov[0].iov_len); /* * Second iovec has the last ciphertext block */ ct.cd_uio->uio_iov[1].iov_base = tmp_ct; ct.cd_uio->uio_iov[1].iov_len = BLOCK_SIZE; /* This had better be AES CBC mode! */ mech.cm_type = key->kef_mt; if (ivec == NULL) { bzero(local_iv_data, sizeof (local_iv_data)); mech.cm_param = local_iv_data; mech.cm_param_len = sizeof (local_iv_data); } else { mech.cm_param = ivec->data; mech.cm_param_len = ivec->length; } /* encrypt using AES CBC */ ret = crypto_encrypt(&mech, &pt, (crypto_key_t *)&key->kef_key, key->key_tmpl, &ct, NULL); if (ret != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR, "crypto_encrypt: error: ret = 0x%08x", ret); goto cleanup; } /* * Swap: * copy the next to last ct to last partial output block (only * the partial amount is copied). */ nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE)); lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE)); bcopy(nlobp, lobp, partialamount); /* * copy the last ct output block to next to last output block */ bcopy(tmp_ct, nlobp, BLOCK_SIZE); } /* end partial block processing */ /* * The ivec is updated to allow the caller to chain ivecs. At this * point I don't think any kernel callers are using this however the * userland version of this function does it so this should be done in * kernel for consistency's sake. This is not done for 1 block, got * this from MIT. Note, the next to last output block is copied because * it contains the last full block of cipher text. */ if (nblocks > 1 && ivec) (void) memcpy(ivec->data, nlobp, BLOCK_SIZE); cleanup: if (ret) bzero(output->data, output->length); return (ret); } #else /* User Space */ /*ARGSUSED*/ krb5_error_code krb5int_aes_encrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; int nblocks, partialamount; CK_RV rv; KRB5_MECH_TO_PKCS algos; CK_MECHANISM mechanism; CK_ULONG outlen; /* * nlobp = next to last output block pointer, lobp = last output block * pointer */ char *nlobp, *lobp; char tmp_ivec[BLOCK_SIZE]; assert(input != NULL); if (input->length < BLOCK_SIZE) return (KRB5_BAD_MSIZE); assert(output != NULL); assert(input->length == output->length); assert(key != NULL); if (ivec != NULL) { /* * This function updates ivec->data if the ivec is passed in so * it better have a data pointer and a proper length. */ if (ivec->data == NULL || ivec->length != BLOCK_SIZE) { assert(ivec->data != NULL); assert(ivec->length == BLOCK_SIZE); KRB5_LOG1(KRB5_ERR, "In krb5int_aes_encrypt: error " "ivec->data = %p ivec->length = %d", ivec->data, ivec->length); ret = KRB5_CRYPTO_INTERNAL; goto cleanup; } } /* number of input blocks including partial block */ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks); /* get # of bytes in partially filled block */ partialamount = input->length % BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount); rv = get_algo(key->enctype, &algos); if (rv != CKR_OK) goto cleanup; assert(algos.enc_algo == CKM_AES_CBC); rv = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key); if (rv != CKR_OK) goto cleanup; mechanism.mechanism = algos.enc_algo; if (ivec == NULL) { bzero(tmp_ivec, sizeof (tmp_ivec)); mechanism.pParameter = tmp_ivec; mechanism.ulParameterLen = sizeof (tmp_ivec); } else { mechanism.pParameter = ivec->data; mechanism.ulParameterLen = ivec->length; } /* * Note, since CBC is assumed to be the underlying mode, this * call to C_EncryptInit is setting the IV. The IV in use here * is either the ivec passed in or a block of 0's. */ rv = C_EncryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptInit failed in " "krb5int_aes_encrypt: rv = 0x%x", rv); goto cleanup; } if (nblocks == 1 || (partialamount == 0)) { /* * Simple case: * * Use CBC for all plaintext blocks, all must be full, then swap * last 2 ciphertext blocks to implement CTS. */ /* * C_Encrypt/Decrypt requires a pointer to long, not a pointer * to int cast to pointer to long!!! */ outlen = output->length; rv = C_Encrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, input->length, (CK_BYTE_PTR)output->data, &outlen); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_Encrypt failed in " "krb5int_aes_encrypt: rv = 0x%x", rv); goto cleanup; } assert(output->length == (unsigned int)outlen); if (nblocks > 1) { /* * swap last 2 ciphertext blocks to implement CTS */ char tmp[BLOCK_SIZE]; nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE)); lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE)); bcopy(nlobp, tmp, BLOCK_SIZE); bcopy(lobp, nlobp, BLOCK_SIZE); bcopy(tmp, lobp, BLOCK_SIZE); } } else { /* * Complex case: * * This implements CTS mode where there is > 1 block and the * last block is partially filled. Uses CBC mode in uCF/PKCS11, * then does some swapping. * * pt = plain text, ct = cipher text */ char tmp_pt[BLOCK_SIZE], tmp_ct[BLOCK_SIZE]; /* * encrypt from P0...Pn-1 using CBC, last block of output is Cn * & C' */ outlen = input->length - partialamount; rv = C_EncryptUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, input->length - partialamount, (CK_BYTE_PTR)output->data, &outlen); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptUpdate failed in " "krb5int_aes_encrypt: rv = 0x%x", rv); goto cleanup; } /* tmp_pt will provide 0 padding for last parital pt block */ bzero(tmp_pt, sizeof (tmp_pt)); /* copy Pn to tmp_pt which has 0 padding */ bcopy(input->data + (input->length - partialamount), tmp_pt, partialamount); /* encrypt Pn with 0 padding, Cn & C' ivec, output is Cn-1 */ outlen = sizeof (tmp_ct); rv = C_EncryptUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)tmp_pt, BLOCK_SIZE, (CK_BYTE_PTR)tmp_ct, &outlen); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_Encrypt failed in " "krb5int_aes_encrypt: rv = 0x%x", rv); goto cleanup; } nlobp = (char *)(output->data + ((nblocks - 2) * BLOCK_SIZE)); lobp = (char *)(output->data + ((nblocks - 1) * BLOCK_SIZE)); /* copy Cn from next to last output block to last block */ bcopy(nlobp, lobp, partialamount); /* copy Cn-1 from tmp_ct to next to last output block */ bcopy(tmp_ct, nlobp, BLOCK_SIZE); /* Close the crypto session, ignore the output */ rv = C_EncryptFinal(krb_ctx_hSession(context), (CK_BYTE_PTR)tmp_ct, &outlen); if (rv != CKR_OK) goto cleanup; } /* * The ivec is updated to allow the caller to chain ivecs, done for the * kcmd (rsh/rcp/etc...). Note this is not done for 1 block although I * am not sure why but I'm continuing the tradition from the MIT code. * Note, the next to last output block is copied because it contains the * last full block of cipher text. */ if (nblocks > 1 && ivec) (void) memcpy(ivec->data, nlobp, BLOCK_SIZE); cleanup: if (rv != CKR_OK) ret = PKCS_ERR; if (ret) bzero(output->data, input->length); return (ret); } #endif /* _KERNEL */ /* * AES Decrypt using CipherText Stealing mode built on top of CBC mode. See the * krb5int_aes_encrypt() comments for the reason CBC is being used. */ #ifdef _KERNEL /*ARGSUSED*/ krb5_error_code krb5int_aes_decrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; int nblocks, partialamount; char local_iv_data[BLOCK_SIZE]; krb5_data local_iv; KRB5_LOG0(KRB5_INFO, "In krb5int_aes_decrypt: start"); ASSERT(input != NULL); if (input->length < BLOCK_SIZE) return (KRB5_BAD_MSIZE); ASSERT(output != NULL); ASSERT(input->length == output->length); ASSERT(key != NULL); ASSERT(key->kef_mt == crypto_mech2id(SUN_CKM_AES_CBC)); if (ivec != NULL) { /* * This function updates ivec->data if the ivec is passed in so * it better have a data pointer and a proper length. */ if (ivec->data == NULL || ivec->length != BLOCK_SIZE) { ASSERT(ivec->data != NULL); ASSERT(ivec->length == BLOCK_SIZE); KRB5_LOG1(KRB5_ERR, "In krb5int_aes_decrypt: error " "ivec->data = %p ivec->length = %d", (void *)ivec->data, ivec->length); ret = KRB5_CRYPTO_INTERNAL; goto cleanup; } } /* number of input blocks including partial block */ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks); /* get # of bytes in partially filled block */ partialamount = input->length % BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount); if (ivec != NULL) { local_iv.data = ivec->data; local_iv.length = ivec->length; } else { bzero(local_iv_data, sizeof (local_iv_data)); local_iv.data = local_iv_data; local_iv.length = sizeof (local_iv_data); } if (nblocks == 1 || (partialamount == 0)) { char orig_input[BLOCK_SIZE * 2]; /* * nlibp = next to last input block pointer * libp = last input block pointer */ char *nlibp, *libp; /* * Simple case: * * Swap last 2 ciphertext blocks (all must be full), then use * CBC to implement CTS. */ if (nblocks > 1) { /* * swap last 2 ciphertext blocks to implement CTS */ char tmp[BLOCK_SIZE]; nlibp = input->data + ((nblocks - 2) * BLOCK_SIZE); libp = input->data + ((nblocks - 1) * BLOCK_SIZE); /* first save orig input data for later restore */ /* we know that partial amount is 0, because */ /* nblocks is > 1, so we copy the last two blocks */ bcopy(nlibp, orig_input, sizeof (orig_input)); /* swap */ bcopy(nlibp, tmp, BLOCK_SIZE); bcopy(libp, nlibp, BLOCK_SIZE); bcopy(tmp, libp, BLOCK_SIZE); } ret = k5_ef_crypto((const char *)input->data, (char *)output->data, input->length, (krb5_keyblock *)key, &local_iv, FALSE); if (nblocks > 1) { /* restore orig input data */ bcopy(orig_input, nlibp, sizeof (orig_input)); } if (ret != 0) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto returned error: ret = 0x%08x", ret); goto cleanup; } } else { krb5_data tmp_ivec; char tmp_ivec_data[BLOCK_SIZE], tmp_input_data[BLOCK_SIZE], tmp_output_data[BLOCK_SIZE]; /* pointers to Cn, Cn-1, Cn-2 CipherText */ char *Cn, *Cn_1, *Cn_2; long length; /* * Complex case: * * Decrypting in CTS where there is a partial block of * ciphertext. */ /* setting pointers to CipherText for later use */ Cn = input->data + (input->length - partialamount); /* Cn - 1 */ Cn_1 = Cn - BLOCK_SIZE; /* Cn - 2 */ Cn_2 = Cn_1 - BLOCK_SIZE; if (nblocks > 2) { /* set length to include blocks C0 thru Cn-2 */ length = input->length - (BLOCK_SIZE + partialamount); /* * First decrypt C0 thru Cn-2 using CBC with the input * ivec. */ ret = k5_ef_crypto((const char *)input->data, output->data, length, (krb5_keyblock *)key, &local_iv, FALSE); if (ret != 0) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto: error: ret = 0x%08x", ret); goto cleanup; } } /* * Prepare to decrypt Cn-1 using a ivec of Cn with 0 padding. */ bzero(tmp_ivec_data, sizeof (tmp_ivec_data)); /* the tmp ivec data holds Cn with 0 padding */ bcopy(Cn, tmp_ivec_data, partialamount); tmp_ivec.data = tmp_ivec_data; tmp_ivec.length = sizeof (tmp_ivec_data); /* decrypt 1 block */ length = BLOCK_SIZE; /* * Now decrypt using Cn-1 input, Cn + 0 padding for ivec, Pn & * C' output */ ret = k5_ef_crypto((const char *)Cn_1, tmp_output_data, length, (krb5_keyblock *)key, &tmp_ivec, FALSE); if (ret != 0) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto: error: ret = 0x%08x", ret); goto cleanup; } /* * tmp input data should hold Cn with C' * Note, tmp_output_data contains Pn + C', */ /* copy Cn */ bcopy(Cn, tmp_input_data, partialamount); /* copy C' */ bcopy(tmp_output_data + partialamount, tmp_input_data + partialamount, (BLOCK_SIZE - partialamount)); /* copy Pn in tmp output to output->data */ bcopy(tmp_output_data, output->data + (input->length - partialamount), partialamount); if (nblocks > 2) { /* use Cn-2 as ivec */ tmp_ivec.data = Cn_2; } else { /* use 0 as ivec because Cn-2 does not exist */ bzero(tmp_ivec_data, sizeof (tmp_ivec_data)); } /* * Now decrypt Cn + C' input, using either Cn-2 or 0 for ivec * (set above), Pn-1 output. */ ret = k5_ef_crypto((const char *)tmp_input_data, (char *)output->data + (input->length - (BLOCK_SIZE + partialamount)), length, (krb5_keyblock *)key, &tmp_ivec, FALSE); if (ret != 0) { KRB5_LOG(KRB5_ERR, "k5_ef_crypto: error: ret = 0x%08x", ret); goto cleanup; } } /* end partial block processing */ /* * The ivec is updated to allow the caller to chain ivecs. At this * point I don't think any kernel callers are using this however the * userland version of this function does it so this should be done in * kernel for consistency's sake. This is not done for 1 block, got * this from MIT. */ if (nblocks > 1 && ivec) { (void) memcpy(ivec->data, input->data + ((nblocks - 2) * BLOCK_SIZE), BLOCK_SIZE); } cleanup: if (ret) bzero(output->data, output->length); return (ret); } #else /* User Space */ /*ARGSUSED*/ krb5_error_code krb5int_aes_decrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; int nblocks, partialamount; CK_RV rv; KRB5_MECH_TO_PKCS algos; CK_MECHANISM mechanism; CK_ULONG outlen; char tmp_ivec[BLOCK_SIZE]; assert(input != NULL); if (input->length < BLOCK_SIZE) return (KRB5_BAD_MSIZE); assert(output != NULL); assert(input->length == output->length); assert(key != NULL); if (ivec != NULL) { /* * This function updates ivec->data if the ivec is passed in so * it better have a data pointer and a proper length. */ if (ivec->data == NULL || ivec->length != BLOCK_SIZE) { assert(ivec->data != NULL); assert(ivec->length == BLOCK_SIZE); KRB5_LOG1(KRB5_ERR, "In krb5int_aes_decrypt: error " "ivec->data = %p ivec->length = %d", ivec->data, ivec->length); ret = KRB5_CRYPTO_INTERNAL; goto cleanup; } } /* number of input blocks including partial block */ nblocks = (input->length + BLOCK_SIZE - 1) / BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "nblocks = %d", nblocks); /* get # of bytes in partially filled block */ partialamount = input->length % BLOCK_SIZE; KRB5_LOG(KRB5_INFO, "partialamount = %d", partialamount); rv = get_algo(key->enctype, &algos); if (rv != CKR_OK) goto cleanup; assert(algos.enc_algo == CKM_AES_CBC); rv = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key); if (rv != CKR_OK) { goto cleanup; } mechanism.mechanism = algos.enc_algo; if (ivec == NULL) { bzero(tmp_ivec, sizeof (tmp_ivec)); mechanism.pParameter = tmp_ivec; mechanism.ulParameterLen = sizeof (tmp_ivec); } else { mechanism.pParameter = ivec->data; mechanism.ulParameterLen = ivec->length; } if (nblocks == 1 || (partialamount == 0)) { char orig_input[BLOCK_SIZE * 2]; /* * nlibp = next to last input block pointer * libp = last input block pointer */ char *nlibp, *libp; /* * Simple case: * * Swap last 2 ciphertext blocks (all must be full), then use * CBC to implement CTS. */ if (nblocks > 1) { /* * swap last 2 ciphertext blocks to implement CTS */ char tmp[BLOCK_SIZE]; /* * Note, the side effect with this is that we are * modifying the input->data! */ nlibp = input->data + ((nblocks - 2) * BLOCK_SIZE); libp = input->data + ((nblocks - 1) * BLOCK_SIZE); /* first save orig input data for later restore */ /* we know that partial amount is 0, because */ /* nblocks is > 1, so we copy the last two blocks */ bcopy(nlibp, orig_input, sizeof (orig_input)); bcopy(nlibp, tmp, BLOCK_SIZE); bcopy(libp, nlibp, BLOCK_SIZE); bcopy(tmp, libp, BLOCK_SIZE); } /* * Note, since CBC is assumed to be the underlying mode, this * call to C_DecryptInit is setting the IV. The IV in use here * is either the ivec passed in or a block of 0's. All calls to * C_DecryptInit set the IV in this function. */ rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in " "krb5int_aes_decrypt: rv = 0x%x", rv); goto cleanup; } /* * C_Encrypt/Decrypt requires a pointer to long, not a pointer * to int cast to pointer to long!!! */ outlen = output->length; rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, input->length, (CK_BYTE_PTR)output->data, &outlen); if (nblocks > 1) { /* restore orig input data */ bcopy(orig_input, nlibp, sizeof (orig_input)); } } else { char tmp_ivec_data[BLOCK_SIZE], tmp_input_data[BLOCK_SIZE], tmp_output_data[BLOCK_SIZE]; /* pointers to Cn, Cn-1, Cn-2 CipherText */ char *Cn, *Cn_1, *Cn_2; CK_ULONG length; /* * Complex case: * * Decrypting in CTS where there is a partial block of * ciphertext. */ /* setting pointers to CipherText for later use */ Cn = input->data + (input->length - partialamount); /* Cn - 1 */ Cn_1 = Cn - BLOCK_SIZE; /* Cn - 2 */ Cn_2 = Cn_1 - BLOCK_SIZE; if (nblocks > 2) { rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in " "krb5int_aes_decrypt: rv = 0x%x", rv); goto cleanup; } /* set length to include blocks C0 thru Cn-2 */ length = input->length - (BLOCK_SIZE + partialamount); outlen = length; /* * First decrypt C0 thru Cn-2 using CBC with the input * ivec. */ rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, length, (CK_BYTE_PTR)output->data, &outlen); if (rv != CKR_OK) goto cleanup; } /* * Prepare to decrypt Cn-1 using a ivec of Cn with 0 padding. */ bzero(tmp_ivec_data, sizeof (tmp_ivec_data)); /* the tmp ivec data holds Cn with 0 padding */ bcopy(Cn, tmp_ivec_data, partialamount); /* decrypt 1 block */ length = BLOCK_SIZE; outlen = length; /* set ivec to Cn with 0 padding */ mechanism.pParameter = tmp_ivec_data; mechanism.ulParameterLen = sizeof (tmp_ivec_data); rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in " "krb5int_aes_decrypt: rv = 0x%x", rv); goto cleanup; } /* * Now decrypt using Cn-1 input, Cn + 0 padding for ivec, Pn & * C' output */ rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)Cn_1, length, (CK_BYTE_PTR)tmp_output_data, &outlen); if (rv != CKR_OK) goto cleanup; /* * tmp input data should hold Cn with C' * Note, tmp_output_data contains Pn + C', */ /* copy Cn */ bcopy(Cn, tmp_input_data, partialamount); /* copy C' */ bcopy(tmp_output_data + partialamount, tmp_input_data + partialamount, (BLOCK_SIZE - partialamount)); /* copy Pn in tmp output to output->data last block */ bcopy(tmp_output_data, output->data + (input->length - partialamount), partialamount); if (nblocks > 2) { /* use Cn-2 as ivec */ mechanism.pParameter = Cn_2; } else { /* * nblocks == 2 * * Cn-2 does not exist so either use 0 if input ivec * does not exist or use the input ivec. */ if (ivec == NULL) { bzero(tmp_ivec_data, sizeof (tmp_ivec_data)); } else { /* use original input ivec */ mechanism.pParameter = ivec->data; mechanism.ulParameterLen = ivec->length; } } rv = C_DecryptInit(krb_ctx_hSession(context), &mechanism, key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in " "krb5int_aes_decrypt: rv = 0x%x", rv); goto cleanup; } /* * Now decrypt Cn + C' input, using either Cn-2, original input * ivec or 0 for ivec (set above), Pn-1 output. */ rv = C_Decrypt(krb_ctx_hSession(context), (CK_BYTE_PTR)tmp_input_data, length, (CK_BYTE_PTR)output->data + (input->length - (BLOCK_SIZE + partialamount)), &outlen); if (rv != CKR_OK) goto cleanup; } /* end partial block processing */ /* * The ivec is updated to allow the caller to chain ivecs, done for the * kcmd (rsh/rcp/etc...). Note this is not done for 1 block although I * am not sure why but I'm continuing the tradition from the MIT code. */ if (nblocks > 1 && ivec) { (void) memcpy(ivec->data, input->data + ((nblocks - 2) * BLOCK_SIZE), BLOCK_SIZE); } cleanup: if (rv != CKR_OK) ret = PKCS_ERR; if (ret) bzero(output->data, input->length); return (ret); } #endif /* _KERNEL */ static krb5_error_code k5_aes_make_key(krb5_context context, const krb5_data *randombits, krb5_keyblock *key) { krb5_error_code ret = 0; if (key->length != 16 && key->length != 32) return (KRB5_BAD_KEYSIZE); if (randombits->length != key->length) return (KRB5_CRYPTO_INTERNAL); key->magic = KV5M_KEYBLOCK; key->dk_list = NULL; #ifdef _KERNEL key->kef_key.ck_data = NULL; key->key_tmpl = NULL; (void) memcpy(key->contents, randombits->data, randombits->length); ret = init_key_kef(context->kef_cipher_mt, key); #else key->hKey = CK_INVALID_HANDLE; (void) memcpy(key->contents, randombits->data, randombits->length); ret = init_key_uef(krb_ctx_hSession(context), key); #endif /* _KERNEL */ KRB5_LOG0(KRB5_INFO, "k5_aes_make_key() end\n"); return (ret); } /*ARGSUSED*/ static krb5_error_code krb5int_aes_init_state(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, krb5_data *state) { if (!state) return (0); if (state && state->data) FREE(state->data, state->length); state->length = BLOCK_SIZE; state->data = (void *) MALLOC(BLOCK_SIZE); if (state->data == NULL) return (ENOMEM); (void) memset(state->data, 0, state->length); return (0); } const struct krb5_enc_provider krb5int_enc_aes128 = { BLOCK_SIZE, 16, 16, krb5int_aes_encrypt, krb5int_aes_decrypt, k5_aes_make_key, krb5int_aes_init_state, krb5int_default_free_state }; const struct krb5_enc_provider krb5int_enc_aes256 = { BLOCK_SIZE, 32, 32, krb5int_aes_encrypt, krb5int_aes_decrypt, k5_aes_make_key, krb5int_aes_init_state, krb5int_default_free_state }; /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2000 by Computer Science Laboratory, * Rensselaer Polytechnic Institute * #include STD_DISCLAIMER */ #include #include /* from a random bitstrem, construct a key */ static krb5_error_code k5_arcfour_make_key(krb5_context, const krb5_data *, krb5_keyblock *); #ifndef _KERNEL static krb5_error_code setup_arcfour_crypto(CK_SESSION_HANDLE session, const krb5_keyblock *key, KRB5_MECH_TO_PKCS *algos, CK_OBJECT_HANDLE *hKey) { krb5_error_code ret = 0; CK_RV rv; CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_RC4; CK_BBOOL true = TRUE, false = FALSE; CK_ATTRIBUTE template[5]; if ((rv = get_algo(key->enctype, algos)) != CKR_OK) { KRB5_LOG0(KRB5_ERR, "failure to get algo id in function " "k5_arcfour_decrypt."); return (PKCS_ERR); } template[0].type = CKA_CLASS; template[0].pValue = &class; template[0].ulValueLen = sizeof (class); template[1].type = CKA_KEY_TYPE; template[1].pValue = &keyType; template[1].ulValueLen = sizeof (keyType); template[2].type = CKA_TOKEN; template[2].pValue = &false; template[2].ulValueLen = sizeof (false); template[3].type = CKA_ENCRYPT; template[3].pValue = &true; template[3].ulValueLen = sizeof (true); template[4].type = CKA_VALUE; template[4].pValue = key->contents; template[4].ulValueLen = key->length; /* Create an object handle for the key */ if ((rv = C_CreateObject(session, template, sizeof(template)/sizeof(CK_ATTRIBUTE), hKey)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_CreateObject failed in " "k5_arcfour_decrypt: rv = 0x%x.", rv); ret = PKCS_ERR; } return (ret); } #endif /* !_KERNEL */ /* The workhorse of the arcfour system, this impliments the cipher */ /* ARGSUSED */ static krb5_error_code k5_arcfour_decrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *state, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; #ifndef _KERNEL CK_RV rv; KRB5_MECH_TO_PKCS algos; CK_OBJECT_HANDLE *kptr = NULL, hKey = CK_INVALID_HANDLE; CK_MECHANISM mechanism; CK_SESSION_HANDLE session = 0; CK_ULONG outlen; int need_init = 0; #endif KRB5_LOG0(KRB5_INFO, "k5_arcfour_decrypt start"); if (key->length != 16) return(KRB5_BAD_KEYSIZE); if (input->length != output->length) return(KRB5_BAD_MSIZE); #ifndef _KERNEL /* * If RC4 is being used to encrypt a stream of data blocks, * the keys for encrypt and decrypt must be kept separate * so that their associated state data doesn't get mixed up * between operations. The r-cmds (rlogin, rsh, rcp) use * the "init_state" function (see bottom of this module) * to set up and prepare for stream encryption. * * Normally, the RC4 key is used as a single operation * (i.e. call C_Encrypt) instead of a constantly updating * stream cipher (C_EncryptUpdate). In those cases, we just * use a short-term key object defined locally. We don't * have to save state between operations. * * This logic here is to make sure that the keys are tracked * correctly depending on how they are used and that the RC4 * context record is properly initialized. */ if (!context->arcfour_ctx.initialized) { session = krb_ctx_hSession(context); /* Just use a local, 1-time only key object */ kptr = (CK_OBJECT_HANDLE *)&hKey; need_init = 1; } else { session = context->arcfour_ctx.dSession; /* If the dKey handle was not defined, we need to initialize one */ if (context->arcfour_ctx.dKey == CK_INVALID_HANDLE) { need_init = 1; /* Use the long-term key object in the RC4 context area */ kptr = &context->arcfour_ctx.dKey; } } if (need_init) { ret = setup_arcfour_crypto(session, key, &algos, kptr); if (ret) goto cleanup; mechanism.mechanism = algos.enc_algo; mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; rv = C_DecryptInit(session, &mechanism, *kptr); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptInit failed in " "k5_arcfour_decrypt: rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } } outlen = (CK_ULONG)output->length; if (context->arcfour_ctx.initialized) rv = C_DecryptUpdate(session, (CK_BYTE_PTR)input->data, (CK_ULONG)input->length, (CK_BYTE_PTR)output->data, (CK_ULONG_PTR)&outlen); else { rv = C_Decrypt(session, (CK_BYTE_PTR)input->data, (CK_ULONG)input->length, (CK_BYTE_PTR)output->data, (CK_ULONG_PTR)&outlen); } output->length = (uint32_t)outlen; if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DecryptUpdate failed in k5_arcfour_decrypt: " "rv = 0x%x", rv); ret = PKCS_ERR; } cleanup: if (ret) bzero(output->data, input->length); /* If we used a 1-time only key object, destroy it now */ if (hKey != CK_INVALID_HANDLE) (void)C_DestroyObject(session, hKey); #else /* !_KERNEL */ KRB5_LOG(KRB5_INFO, "key->kef_mt = %ld", (ulong_t) key->kef_mt); ret = k5_ef_crypto((const char *)input->data, (char *)output->data, input->length, (krb5_keyblock *)key, NULL, 0); #endif /* !_KERNEL */ KRB5_LOG0(KRB5_INFO, "k5_arcfour_docrypt end"); return (ret); } /* ARGSUSED */ static krb5_error_code k5_arcfour_encrypt(krb5_context context, const krb5_keyblock *key, const krb5_data *state, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; #ifndef _KERNEL CK_RV rv; KRB5_MECH_TO_PKCS algos; CK_MECHANISM mechanism; CK_OBJECT_HANDLE *kptr = NULL, hKey = CK_INVALID_HANDLE; CK_SESSION_HANDLE session; int need_init = 0; CK_ULONG outlen; #endif KRB5_LOG0(KRB5_INFO, "k5_arcfour_encrypt start"); if (key->length != 16) return(KRB5_BAD_KEYSIZE); if (input->length != output->length) return(KRB5_BAD_MSIZE); #ifndef _KERNEL /* * See the comments in the k5_arcfour_decrypt routine (above) * for an explanation of why the key handles are initialized * and used as they are here. */ if (!context->arcfour_ctx.initialized) { session = krb_ctx_hSession(context); kptr = (CK_OBJECT_HANDLE *)&hKey; need_init = 1; } else { session = context->arcfour_ctx.eSession; if (context->arcfour_ctx.eKey == 0) { kptr = &context->arcfour_ctx.eKey; need_init = 1; } } if (need_init) { ret = setup_arcfour_crypto(session, key, &algos, kptr); if (ret) goto cleanup; mechanism.mechanism = algos.enc_algo; mechanism.pParameter = NULL; mechanism.ulParameterLen = 0; rv = C_EncryptInit(session, &mechanism, *kptr); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptInit failed in " "k5_arcfour_encrypt: rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } } /* * If we've initialize the stream for use with r-commands, * use the open-ended session handle and call. */ outlen = (CK_ULONG)output->length; if (context->arcfour_ctx.initialized) rv = C_EncryptUpdate(session, (CK_BYTE_PTR)input->data, (CK_ULONG)input->length, (CK_BYTE_PTR)output->data, (CK_ULONG_PTR)&outlen); else { rv = C_Encrypt(session, (CK_BYTE_PTR)input->data, (CK_ULONG)input->length, (CK_BYTE_PTR)output->data, (CK_ULONG_PTR)&outlen); } output->length = (uint32_t)outlen; if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_EncryptUpdate failed in k5_arcfour_encrypt: " "rv = 0x%x", rv); ret = PKCS_ERR; } cleanup: if (ret) bzero(output->data, input->length); if (hKey != CK_INVALID_HANDLE) (void)C_DestroyObject(session, hKey); #else /* !_KERNEL */ KRB5_LOG1(KRB5_INFO, "key->kef_mt = %ld key->key_tmpl = %ld", (ulong_t) key->kef_mt, (ulong_t) key->key_tmpl); ret = k5_ef_crypto((const char *)input->data, (char *)output->data, input->length, (krb5_keyblock *)key, NULL, 1); #endif /* !_KERNEL */ KRB5_LOG0(KRB5_INFO, "k5_arcfour_docrypt end"); return (ret); } /* ARGSUSED */ static krb5_error_code k5_arcfour_make_key(krb5_context context, const krb5_data *randombits, krb5_keyblock *key) { krb5_error_code ret = 0; KRB5_LOG0(KRB5_INFO, "k5_arcfour_make_key() start\n"); if (key->length != 16) return(KRB5_BAD_KEYSIZE); if (randombits->length != 16) return(KRB5_CRYPTO_INTERNAL); key->magic = KV5M_KEYBLOCK; key->length = 16; key->dk_list = NULL; #ifdef _KERNEL key->kef_key.ck_data = NULL; key->key_tmpl = NULL; ret = init_key_kef(context->kef_cipher_mt, key); #else key->hKey = CK_INVALID_HANDLE; ret = init_key_uef(krb_ctx_hSession(context), key); #endif /* _KERNEL */ bcopy(randombits->data, key->contents, randombits->length); KRB5_LOG0(KRB5_INFO, "k5_arcfour_make_key() end\n"); return (ret); } /*ARGSUSED*/ static krb5_error_code k5_arcfour_init_state (krb5_context context, const krb5_keyblock *key, krb5_keyusage keyusage, krb5_data *new_state) { krb5_error_code retval = 0; #ifndef _KERNEL if (!context->arcfour_ctx.initialized) { retval = krb5_open_pkcs11_session(&context->arcfour_ctx.eSession); if (retval) return (retval); retval = krb5_open_pkcs11_session(&context->arcfour_ctx.dSession); if (retval) return (retval); context->arcfour_ctx.initialized = 1; context->arcfour_ctx.eKey = CK_INVALID_HANDLE; context->arcfour_ctx.dKey = CK_INVALID_HANDLE; } #endif return (retval); } /* Since the arcfour cipher is identical going forwards and backwards, we just call "docrypt" directly */ const struct krb5_enc_provider krb5int_enc_arcfour = { 1, 16, 16, k5_arcfour_encrypt, k5_arcfour_decrypt, k5_arcfour_make_key, k5_arcfour_init_state, krb5int_default_free_state }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "des_int.h" #include "enc_provider.h" static krb5_error_code k5_des_docrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output, int encrypt) { krb5_error_code ret; KRB5_LOG(KRB5_INFO, "k5_des_docrypt() start encrypt=%d\n", encrypt); /* key->enctype was checked by the caller */ if (key->length != 8) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); if (ivec && (ivec->length != 8)) return(KRB5_BAD_MSIZE); if (input->length != output->length) return(KRB5_BAD_MSIZE); ret = mit_des_cbc_encrypt(context, (krb5_pointer) input->data, (krb5_pointer) output->data, input->length, (krb5_keyblock *)key, ivec?(unsigned char *)ivec->data: (unsigned char *)mit_des_zeroblock, encrypt); KRB5_LOG0(KRB5_INFO, "k5_des_docrypt() end\n"); return(ret); } static krb5_error_code k5_des_encrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { return(k5_des_docrypt(context, key, ivec, input, output, 1)); } static krb5_error_code k5_des_decrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { return(k5_des_docrypt(context, key, ivec, input, output, 0)); } static krb5_error_code k5_des_make_key(krb5_context context, krb5_const krb5_data *randombits, krb5_keyblock *key) { krb5_error_code ret = 0; if (key->length != 8) return(KRB5_BAD_KEYSIZE); if (randombits->length != 7) return(KRB5_CRYPTO_INTERNAL); key->magic = KV5M_KEYBLOCK; key->length = 8; key->dk_list = NULL; /* take the seven bytes, move them around into the top 7 bits of the 8 key bytes, then compute the parity bits */ (void) memcpy(key->contents, randombits->data, randombits->length); key->contents[7] = (((key->contents[0]&1)<<1) | ((key->contents[1]&1)<<2) | ((key->contents[2]&1)<<3) | ((key->contents[3]&1)<<4) | ((key->contents[4]&1)<<5) | ((key->contents[5]&1)<<6) | ((key->contents[6]&1)<<7)); mit_des_fixup_key_parity(key->contents); #ifdef _KERNEL key->kef_key.ck_data = NULL; key->key_tmpl = NULL; ret = init_key_kef(context->kef_cipher_mt, key); #else key->hKey = CK_INVALID_HANDLE; ret = init_key_uef(krb_ctx_hSession(context), key); #endif /* _KERNEL */ return (ret); } const struct krb5_enc_provider krb5int_enc_des = { 8, 7, 8, k5_des_encrypt, k5_des_decrypt, k5_des_make_key, krb5int_des_init_state, krb5int_default_free_state }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "des_int.h" static krb5_error_code k5_des3_docrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output, int encrypt) { /* LINTED */ krb5_error_code ret; KRB5_LOG0(KRB5_INFO, "k5_des3_docrypt() start"); /* key->enctype was checked by the caller */ if (key->length != 24) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); if (ivec && (ivec->length != 8)) return(KRB5_BAD_MSIZE); if (input->length != output->length) return(KRB5_BAD_MSIZE); ret = mit_des3_cbc_encrypt(context, (krb5_pointer) input->data, (krb5_pointer) output->data, input->length, (krb5_keyblock *)key, ivec?(unsigned char *)ivec->data:(unsigned char *)mit_des_zeroblock, encrypt); KRB5_LOG0(KRB5_INFO, "k5_des3_docrypt() end\n"); return(ret); } static krb5_error_code k5_des3_encrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { return(k5_des3_docrypt(context, key, ivec, input, output, 1)); } static krb5_error_code k5_des3_decrypt(krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { return(k5_des3_docrypt(context, key, ivec, input, output, 0)); } static krb5_error_code k5_des3_make_key(krb5_context context, krb5_const krb5_data *randombits, krb5_keyblock *key) { int i; krb5_error_code ret = 0; KRB5_LOG0(KRB5_INFO, "k5_des3_make_key() start\n"); if (key->length != 24) return(KRB5_BAD_KEYSIZE); if (randombits->length != 21) return(KRB5_CRYPTO_INTERNAL); key->magic = KV5M_KEYBLOCK; key->length = 24; key->dk_list = NULL; /* take the seven bytes, move them around into the top 7 bits of the 8 key bytes, then compute the parity bits. Do this three times. */ for (i=0; i<3; i++) { (void) memcpy(key->contents+i*8, randombits->data+i*7, 7); key->contents[i*8+7] = (((key->contents[i*8]&1)<<1) | ((key->contents[i*8+1]&1)<<2) | ((key->contents[i*8+2]&1)<<3) | ((key->contents[i*8+3]&1)<<4) | ((key->contents[i*8+4]&1)<<5) | ((key->contents[i*8+5]&1)<<6) | ((key->contents[i*8+6]&1)<<7)); mit_des_fixup_key_parity(key->contents+i*8); } #ifdef _KERNEL key->kef_key.ck_data = NULL; key->key_tmpl = NULL; ret = init_key_kef(context->kef_cipher_mt, key); #else key->hKey = CK_INVALID_HANDLE; ret = init_key_uef(krb_ctx_hSession(context), key); #endif /* _KERNEL */ KRB5_LOG0(KRB5_INFO, "k5_des3_make_key() end\n"); return(ret); } const struct krb5_enc_provider krb5int_enc_des3 = { 8, 21, 24, k5_des3_encrypt, k5_des3_decrypt, k5_des3_make_key, krb5int_des_init_state, krb5int_default_free_state }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "etypes.h" #ifdef _KERNEL krb5_error_code update_key_template(krb5_keyblock *key) { crypto_mechanism_t kef_mech; int rv = 0; krb5_error_code ret = 0; KRB5_LOG0(KRB5_INFO, "update_key_template()"); if (key == NULL) return (ret); /* * Preallocate the crypto_key_t records * needed by the kernel crypto calls later. */ kef_mech.cm_type = key->kef_mt; kef_mech.cm_param = NULL; kef_mech.cm_param_len = 0; /* * Create an template to improve HMAC performance later. */ rv = crypto_create_ctx_template(&kef_mech, &key->kef_key, &key->key_tmpl, KM_SLEEP); if (rv != CRYPTO_SUCCESS) { /* * Some mechs don't support context templates */ if (rv == CRYPTO_NOT_SUPPORTED) { ret = 0; key->key_tmpl = NULL; } else { KRB5_LOG(KRB5_ERR,"crypto_create_ctx_template " "error: %0x", rv); ret = KRB5_KEF_ERROR; } } return (ret); } /* * initialize the KEF components of the krb5_keyblock record. */ krb5_error_code init_key_kef(crypto_mech_type_t mech_type, krb5_keyblock *key) { krb5_error_code rv = 0; KRB5_LOG0(KRB5_INFO, "init_key_kef()"); if (key == NULL) return (rv); if (key->kef_key.ck_data == NULL) { key->kef_key.ck_data = key->contents; } /* kef keys are measured in bits */ key->kef_key.ck_length = key->length * 8; key->kef_key.ck_format = CRYPTO_KEY_RAW; key->kef_mt = mech_type; if (key->key_tmpl == NULL && mech_type != CRYPTO_MECH_INVALID) { rv = update_key_template(key); } return(rv); } #else /* * init_key_uef * Initialize the Userland Encryption Framework fields of the * key block. */ krb5_error_code init_key_uef(CK_SESSION_HANDLE hSession, krb5_keyblock *key) { CK_RV rv = CKR_OK; CK_MECHANISM mechanism; CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_KEY_TYPE keyType; CK_BBOOL true = TRUE, false = FALSE; CK_ATTRIBUTE template[6]; /* If its already initialized, return OK */ /* * fork safety: if the key->pid != __krb5_current_pid then a fork has * taken place and the pkcs11 key handle must be re-acquired. */ if ((key->hKey != CK_INVALID_HANDLE) && (key->pid == __krb5_current_pid)) return (rv); /* fork safety */ key->pid = __krb5_current_pid; if ((rv = get_key_type(key->enctype, &keyType)) != CKR_OK) { KRB5_LOG0(KRB5_ERR, "failure to get key type in function " "init_key_uef."); return (PKCS_ERR); } template[0].type = CKA_CLASS; template[0].pValue = &class; template[0].ulValueLen = sizeof (class); template[1].type = CKA_KEY_TYPE; template[1].pValue = &keyType; template[1].ulValueLen = sizeof (keyType); template[2].type = CKA_TOKEN; template[2].pValue = &false; template[2].ulValueLen = sizeof (false); template[3].type = CKA_ENCRYPT; template[3].pValue = &true; template[3].ulValueLen = sizeof (true); template[4].type = CKA_DECRYPT; template[4].pValue = &true; template[4].ulValueLen = sizeof (true); template[5].type = CKA_VALUE; template[5].pValue = key->contents; template[5].ulValueLen = key->length; /* Create an object handle for the key */ if ((rv = C_CreateObject(hSession, template, sizeof(template)/sizeof(CK_ATTRIBUTE), &key->hKey)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_CreateObject failed in " "init_key_uef: rv = 0x%x.", rv); rv = PKCS_ERR; } return (rv); } #endif /* _KERNEL */ /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_enc_data *output) { krb5_error_code ret; int i; KRB5_LOG(KRB5_INFO, "krb5_c_encrypt start etype = %d", key->enctype); for (i=0; ienctype) break; } if (i == krb5_enctypes_length) return(KRB5_BAD_ENCTYPE); output->magic = KV5M_ENC_DATA; output->kvno = 0; output->enctype = key->enctype; #ifdef _KERNEL context->kef_cipher_mt = krb5_enctypes_list[i].kef_cipher_mt; context->kef_hash_mt = krb5_enctypes_list[i].kef_hash_mt; if (key->kef_key.ck_data == NULL) { if ((ret = init_key_kef(context->kef_cipher_mt, (krb5_keyblock *)key))) return(ret); } #else if ((ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key))) return (ret); #endif /* _KERNEL */ KRB5_LOG0(KRB5_INFO, "krb5_c_encrypt calling encrypt."); return((*(krb5_enctypes_list[i].encrypt)) (context, krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, key, usage, ivec, input, &output->ciphertext)); } /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "etypes.h" /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, size_t inputlen, size_t *length) { int i; for (i=0; i #include #include #include #include #include #include #include /* these will be linear searched. if they ever get big, a binary search or hash table would be better, which means these would need to be sorted. An array would be more efficient, but that assumes that the keytypes are all near each other. I'd rather not make that assumption. */ struct krb5_keytypes krb5_enctypes_list[] = { { ENCTYPE_DES_CBC_CRC, "des-cbc-crc", "DES cbc mode with CRC-32", &krb5int_enc_des, &krb5int_hash_crc32, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, CKSUMTYPE_RSA_MD5, #ifndef _KERNEL krb5int_des_string_to_key, #else SUN_CKM_DES_CBC, NULL, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES_CBC_MD5, "des-cbc-md5", "DES cbc mode with RSA-MD5", &krb5int_enc_des, &krb5int_hash_md5, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, CKSUMTYPE_RSA_MD5, #ifndef _KERNEL krb5int_des_string_to_key, #else SUN_CKM_DES_CBC, SUN_CKM_MD5, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES_CBC_MD5, "des", "DES cbc mode with RSA-MD5", /* alias */ &krb5int_enc_des, &krb5int_hash_md5, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, CKSUMTYPE_RSA_MD5, #ifndef _KERNEL krb5int_des_string_to_key, #else SUN_CKM_DES_CBC, SUN_CKM_MD5, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* _KERNEL */ }, { ENCTYPE_DES_CBC_RAW, "des-cbc-raw", "DES cbc mode raw", &krb5int_enc_des, NULL, krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, 0, #ifndef _KERNEL krb5int_des_string_to_key, #else SUN_CKM_DES_CBC, NULL, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES3_CBC_RAW, "des3-cbc-raw", "Triple DES cbc mode raw", &krb5int_enc_des3, NULL, krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, 0, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES3_CBC, NULL, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES3_CBC_SHA1, "des3-cbc-sha1", "Triple DES cbc mode with HMAC/sha1", &krb5int_enc_des3, &krb5int_hash_sha1, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, CKSUMTYPE_HMAC_SHA1_DES3, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES3_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif }, { ENCTYPE_DES3_CBC_SHA1, /* alias */ "des3-hmac-sha1", "Triple DES cbc mode with HMAC/sha1", &krb5int_enc_des3, &krb5int_hash_sha1, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, CKSUMTYPE_HMAC_SHA1_DES3, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES3_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES3_CBC_SHA1, /* alias */ "des3-cbc-sha1-kd", "Triple DES cbc mode with HMAC/sha1", &krb5int_enc_des3, &krb5int_hash_sha1, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, CKSUMTYPE_HMAC_SHA1_DES3, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES3_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, /* The des3-cbc-hmac-sha1-kd is the official enctype associated with * 3DES/SHA1 in draft-ietf-krb-wg-crypto-00.txt */ { ENCTYPE_DES3_CBC_SHA1, /* alias */ "des3-cbc-hmac-sha1-kd", "Triple DES cbc mode with HMAC/sha1", &krb5int_enc_des3, &krb5int_hash_sha1, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, CKSUMTYPE_HMAC_SHA1_DES3, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES3_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1", "DES with HMAC/sha1", &krb5int_enc_des, &krb5int_hash_sha1, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, 0, #ifndef _KERNEL krb5int_dk_string_to_key, #else SUN_CKM_DES_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC, "arcfour-hmac","ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC, /* alias */ "rc4-hmac", "ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC, /* alias */ "arcfour-hmac-md5", "ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC_EXP, "arcfour-hmac-exp", "Exportable ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */ "rc4-hmac-exp", "Exportable ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */ "arcfour-hmac-md5-exp", "Exportable ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, CKSUMTYPE_HMAC_MD5_ARCFOUR, #ifndef _KERNEL krb5int_arcfour_string_to_key, #else SUN_CKM_RC4, SUN_CKM_MD5_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, /* * Note, all AES enctypes must use SUN_CKM_AES_CBC. See aes_provider.c for * more info. */ { ENCTYPE_AES128_CTS_HMAC_SHA1_96, "aes128-cts-hmac-sha1-96", "AES-128 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes128, &krb5int_hash_sha1, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, CKSUMTYPE_HMAC_SHA1_96_AES128, #ifndef _KERNEL krb5int_aes_string_to_key, #else SUN_CKM_AES_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_AES128_CTS_HMAC_SHA1_96, "aes128-cts", "AES-128 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes128, &krb5int_hash_sha1, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, CKSUMTYPE_HMAC_SHA1_96_AES128, #ifndef _KERNEL krb5int_aes_string_to_key, #else SUN_CKM_AES_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_AES256_CTS_HMAC_SHA1_96, "aes256-cts-hmac-sha1-96", "AES-256 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes256, &krb5int_hash_sha1, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, CKSUMTYPE_HMAC_SHA1_96_AES256, #ifndef _KERNEL krb5int_aes_string_to_key, #else SUN_CKM_AES_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, { ENCTYPE_AES256_CTS_HMAC_SHA1_96, "aes256-cts", "AES-256 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes256, &krb5int_hash_sha1, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, CKSUMTYPE_HMAC_SHA1_96_AES256, #ifndef _KERNEL krb5int_aes_string_to_key, #else SUN_CKM_AES_CBC, SUN_CKM_SHA1_HMAC, CRYPTO_MECH_INVALID, CRYPTO_MECH_INVALID #endif /* !_KERNEL */ }, }; const int krb5_enctypes_length = sizeof(krb5_enctypes_list)/sizeof(struct krb5_keytypes); #ifdef _KERNEL /* * Routine to pre-fetch the mechanism types from KEF so * we dont keep doing this step later. */ void setup_kef_keytypes() { int i; struct krb5_keytypes *kt; for (i=0; ikef_cipher_mt == CRYPTO_MECH_INVALID && kt->mt_e_name != NULL) { krb5_enctypes_list[i].kef_cipher_mt = crypto_mech2id(kt->mt_e_name); } if (kt->kef_hash_mt == CRYPTO_MECH_INVALID && kt->mt_h_name != NULL) { krb5_enctypes_list[i].kef_hash_mt = crypto_mech2id(kt->mt_h_name); } KRB5_LOG1(KRB5_INFO, "setup_kef_keytypes(): %s ==> %ld", kt->mt_e_name, (ulong_t) krb5_enctypes_list[i].kef_cipher_mt); } } /*ARGSUSED*/ crypto_mech_type_t get_cipher_mech_type(krb5_context context, krb5_keyblock *key) { int i; struct krb5_keytypes *kt; if (key == NULL) return (CRYPTO_MECH_INVALID); for (i=0; ietype == key->enctype) { KRB5_LOG1(KRB5_INFO, "get_cipher_mech_type() " "found %s %ld", kt->mt_e_name, (ulong_t) kt->kef_cipher_mt); return (kt->kef_cipher_mt); } } return (CRYPTO_MECH_INVALID); } /*ARGSUSED*/ crypto_mech_type_t get_hash_mech_type(krb5_context context, krb5_keyblock *key) { int i; struct krb5_keytypes *kt; if (key == NULL) return (CRYPTO_MECH_INVALID); for (i=0; ietype == key->enctype) { KRB5_LOG1(KRB5_INFO, "get_hash_mech_type() " "found %s %ld", kt->mt_h_name, (ulong_t) kt->kef_hash_mt); return (kt->kef_hash_mt); } } return (CRYPTO_MECH_INVALID); } #endif /* _KERNEL */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "crc-32.h" #include "hash_provider.h" /* ARGSUSED */ static krb5_error_code k5_crc32_hash(krb5_context context, unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { unsigned long c, cn; int i; if (output->length != CRC32_CKSUM_LENGTH) return(KRB5_CRYPTO_INTERNAL); c = 0; for (i=0; idata[0] = c&0xff; output->data[1] = (c>>8)&0xff; output->data[2] = (c>>16)&0xff; output->data[3] = (c>>24)&0xff; return(0); } const struct krb5_hash_provider krb5int_hash_crc32 = { CRC32_CKSUM_LENGTH, 1, k5_crc32_hash }; /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include int k5_ef_hash(krb5_context context, int icount, const krb5_data *input, krb5_data *output) { int i; int rv = CRYPTO_FAILED; iovec_t v1, v2; crypto_data_t d1, d2; crypto_mechanism_t mech; crypto_context_t ctxp; KRB5_LOG0(KRB5_INFO, "k5_ef_hash() start"); bzero(&d1, sizeof (d1)); bzero(&d2, sizeof (d2)); v2.iov_base = (void *)output->data; v2.iov_len = output->length; d2.cd_format = CRYPTO_DATA_RAW; d2.cd_offset = 0; d2.cd_length = output->length; d2.cd_raw = v2; mech.cm_type = context->kef_cksum_mt; if (mech.cm_type == CRYPTO_MECH_INVALID) { KRB5_LOG(KRB5_ERR, "k5_ef_hash() invalid mech specified: 0x%llx", (long long)context->kef_hash_mt); return (CRYPTO_FAILED); } mech.cm_param = 0; mech.cm_param_len = 0; rv = crypto_digest_init(&mech, &ctxp, NULL); if (rv != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR, "crypto_digest_init error: %0x", rv); return (rv); } for (i = 0; i < icount; i++) { v1.iov_base = (void *)input[i].data; v1.iov_len = input[i].length; d1.cd_length = input[i].length; d1.cd_format = CRYPTO_DATA_RAW; d1.cd_offset = 0; d1.cd_raw = v1; rv = crypto_digest_update(ctxp, &d1, NULL); if (rv != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR, "crypto_digest_update error: %0x", rv); crypto_cancel_ctx(ctxp); return (rv); } } rv = crypto_digest_final(ctxp, &d2, NULL); /* * crypto_digest_final() internally destroys the context. So, we * do not use the context any more. This means we do not call * crypto_cancel_ctx() for the failure case here unlike the failure * case of crypto_digest_update() where we do. */ if (rv != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR, "crypto_digest_final error: %0x", rv); } return (rv); } int k5_ef_mac(krb5_context context, krb5_keyblock *key, krb5_data *ivec, const krb5_data *input, krb5_data *output) { int rv; iovec_t v1, v2; crypto_data_t d1, d2; crypto_mechanism_t mech; KRB5_LOG0(KRB5_INFO, "k5_ef_mac() start"); ASSERT(input != NULL); ASSERT(ivec != NULL); ASSERT(output != NULL); v2.iov_base = (void *)output->data; v2.iov_len = output->length; bzero(&d1, sizeof (d1)); bzero(&d2, sizeof (d2)); d2.cd_format = CRYPTO_DATA_RAW; d2.cd_offset = 0; d2.cd_length = output->length; d2.cd_raw = v2; mech.cm_type = context->kef_hash_mt; if (mech.cm_type == CRYPTO_MECH_INVALID) { KRB5_LOG(KRB5_ERR, "k5_ef_mac() invalid mech specified: 0x%llx", (long long)context->kef_hash_mt); return (CRYPTO_FAILED); } mech.cm_param = ivec->data; mech.cm_param_len = ivec->length; v1.iov_base = (void *)input->data; v1.iov_len = input->length; d1.cd_format = CRYPTO_DATA_RAW; d1.cd_offset = 0; d1.cd_length = input->length; d1.cd_raw = v1; rv = crypto_mac(&mech, &d1, &key->kef_key, key->key_tmpl, &d2, NULL); if (rv != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR, "k5_ef_mac(): crypto_mac error: %0x", rv); } return (rv); } /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Solaris Kerberos: * this code is based on the * usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c * file, but has been modified to use the Solaris resident md5.o kernel * module and associated header /usr/include/sys/md5.o. * This means that the MD5* functions are called instead of krb5_MD5*. */ #include #include #include static krb5_error_code k5_md5_hash(krb5_context context, unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { if (output->length != MD5_CKSUM_LENGTH) return(KRB5_CRYPTO_INTERNAL); if (k5_ef_hash(context, icount, input, output)) return(KRB5_KEF_ERROR); return(0); } const struct krb5_hash_provider krb5int_hash_md5 = { MD5_CKSUM_LENGTH, 64, k5_md5_hash }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Solaris Kerberos: * this code is based on the * usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c * file, but has been modified to use the Solaris resident sha1.o kernel * module and associated header /usr/include/sys/sha1.h. * This means that the SHA1* functions are called instead of shs*. */ #include #include #include static krb5_error_code k5_sha1_hash(krb5_context context, unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; KRB5_LOG0(KRB5_INFO, "k5_sha1_hash() start"); if (output->length != SHS_DIGESTSIZE) { KRB5_LOG1(KRB5_ERR, "k5_sha1_hash() end error " "output->length(%d) != SHS_DIGESTSIZE(%d)", output->length, SHS_DIGESTSIZE); return(KRB5_CRYPTO_INTERNAL); } if (k5_ef_hash(context, icount, input, output)) ret = KRB5_KEF_ERROR; KRB5_LOG0(KRB5_INFO, "k5_sha1_hash() end"); return(ret); } const struct krb5_hash_provider krb5int_hash_sha1 = { SHS_DIGESTSIZE, SHS_DATASIZE, k5_sha1_hash }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" /* Solaris Kerberos */ #ifdef _KERNEL /* * In kernel, use the Kernel encryption framework HMAC * operation, its far more efficient than the MIT method. * Also, a template is used to further improve performance. */ /* ARGSUSED */ krb5_error_code krb5_hmac(krb5_context context, const krb5_keyblock *key, krb5_const krb5_data *input, krb5_data *output) { int rv = CRYPTO_FAILED; crypto_mechanism_t mac_mech; crypto_data_t dd; crypto_data_t mac; KRB5_LOG0(KRB5_INFO, "krb5_hmac() start"); if (output == NULL || output->data == NULL) { KRB5_LOG0(KRB5_INFO, "krb5_hmac() NULL output"); return (rv); } if (input == NULL || input->data == NULL) { KRB5_LOG0(KRB5_INFO, "krb5_hmac() NULL input"); return (rv); } dd.cd_format = CRYPTO_DATA_RAW; dd.cd_offset = 0; dd.cd_length = input->length; dd.cd_raw.iov_base = (char *)input->data; dd.cd_raw.iov_len = input->length; mac.cd_format = CRYPTO_DATA_RAW; mac.cd_offset = 0; mac.cd_length = output->length; mac.cd_raw.iov_base = (char *)output->data; mac.cd_raw.iov_len = output->length; mac_mech.cm_type = context->kef_hash_mt; mac_mech.cm_param = NULL; mac_mech.cm_param_len = 0; rv = crypto_mac(&mac_mech, &dd, (crypto_key_t *)&key->kef_key, key->key_tmpl, &mac, NULL); if (rv != CRYPTO_SUCCESS) { KRB5_LOG(KRB5_ERR,"crypto_mac error: %0x", rv); } KRB5_LOG(KRB5_INFO, "krb5_hmac() end ret=%d\n", rv); return(rv); } #else /* Userland implementation of HMAC algorithm */ /* * the HMAC transform looks like: * * H(K XOR opad, H(K XOR ipad, text)) * * where H is a cryptographic hash * K is an n byte key * ipad is the byte 0x36 repeated blocksize times * opad is the byte 0x5c repeated blocksize times * and text is the data being protected */ krb5_error_code krb5_hmac(krb5_context context, krb5_const struct krb5_hash_provider *hash, krb5_const krb5_keyblock *key, krb5_const unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { size_t hashsize, blocksize; unsigned char *xorkey, *ihash; int i; krb5_data *hashin, hashout; krb5_error_code ret; /* Solaris Kerberos */ KRB5_LOG0(KRB5_INFO, "krb5_hmac() start\n"); if (hash == NULL) { KRB5_LOG0(KRB5_ERR, "krb5_hmac() error hash == NULL\n"); return(EINVAL); } if (key == NULL) { KRB5_LOG0(KRB5_ERR, "krb5_hmac() error key == NULL\n"); return(EINVAL); } if (input == NULL) { KRB5_LOG0(KRB5_ERR, "krb5_hmac() error input == NULL\n"); return(EINVAL); } if (output == NULL) { KRB5_LOG0(KRB5_ERR, "krb5_hmac() error output == NULL\n"); return(EINVAL); } hashsize = hash->hashsize; blocksize = hash->blocksize; if (key->length > blocksize) return(KRB5_CRYPTO_INTERNAL); if (output->length < hashsize) return(KRB5_BAD_MSIZE); /* if this isn't > 0, then there won't be enough space in this array to compute the outer hash */ if (icount == 0) return(KRB5_CRYPTO_INTERNAL); /* allocate space for the xor key, hash input vector, and inner hash */ if ((xorkey = (unsigned char *) MALLOC(blocksize)) == NULL) return(ENOMEM); if ((ihash = (unsigned char *) MALLOC(hashsize)) == NULL) { FREE(xorkey, blocksize); return(ENOMEM); } if ((hashin = (krb5_data *)MALLOC(sizeof(krb5_data)*(icount+1))) == NULL) { FREE(ihash, hashsize); FREE(xorkey, blocksize); return(ENOMEM); } /* create the inner padded key */ /* Solaris Kerberos */ (void) memset(xorkey, 0x36, blocksize); for (i=0; ilength; i++) xorkey[i] ^= key->contents[i]; /* compute the inner hash */ for (i=0; ihash))(context, icount+1, hashin, &hashout)))) goto cleanup; /* create the outer padded key */ /* Solaris Kerberos */ (void) memset(xorkey, 0x5c, blocksize); for (i=0; ilength; i++) xorkey[i] ^= key->contents[i]; /* compute the outer hash */ hashin[0].length = blocksize; hashin[0].data = (char *) xorkey; hashin[1] = hashout; output->length = hashsize; /* Solaris Kerberos */ if ((ret = ((*(hash->hash))(context, 2, hashin, output)))) (void) memset(output->data, 0, output->length); /* ret is set correctly by the prior call */ cleanup: /* Solaris Kerberos */ (void) memset(xorkey, 0, blocksize); (void) memset(ihash, 0, hashsize); FREE(hashin, sizeof(krb5_data)*(icount+1)); FREE(ihash, hashsize); FREE(xorkey, blocksize); /* Solaris Kerberos */ KRB5_LOG(KRB5_INFO, "krb5_hmac() end ret=%d\n", ret); return(ret); } #endif /* _KERNEL */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "des_int.h" #include "keyhash_provider.h" #ifdef _KERNEL #include #include #endif /*ARGSUSED*/ static krb5_error_code k5_descbc_hash(krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { int ret; krb5_data zero_ivec; if (key->length != MIT_DES_KEYSIZE) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); if (ivec && (ivec->length != MIT_DES_BLOCK_LENGTH)) return(KRB5_CRYPTO_INTERNAL); if (output->length != MIT_DES_BLOCK_LENGTH) return(KRB5_CRYPTO_INTERNAL); zero_ivec.data = (char *)mit_des_zeroblock; zero_ivec.length = sizeof(mit_des_zeroblock); ret = k5_ef_mac(context, (krb5_keyblock *)key, ivec ? (krb5_data *)ivec : &zero_ivec, input, output); return(ret); } const struct krb5_keyhash_provider krb5int_keyhash_descbc = { MIT_DES_BLOCK_LENGTH, k5_descbc_hash, NULL }; /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Solaris Kerberos: * this code is based on the * usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c * file, but has been modified to use the Solaris resident md5.o kernel * module and associated header /usr/include/sys/md5.o. * This means that the MD5* functions are called instead of krb5_MD5*. */ #include #include #include #include #include #define CONFLENGTH 8 /* Force acceptance of krb5-beta5 md5des checksum for now. */ #define KRB5_MD5DES_BETA5_COMPAT /* des-cbc(xorkey, conf | rsa-md5(conf | data)) */ /* this could be done in terms of the md5 and des providers, but that's less efficient, and there's no need for this to be generic */ /*ARGSUSED*/ static krb5_error_code k5_md5des_hash(krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; krb5_data data; unsigned char conf[CONFLENGTH]; unsigned char xorkey[MIT_DES_KEYSIZE]; int i; krb5_data *hash_input; char *outptr; krb5_keyblock newkey; if (key->length != MIT_DES_KEYSIZE) return(KRB5_BAD_KEYSIZE); if (ivec) return(KRB5_CRYPTO_INTERNAL); if (output->length != (CONFLENGTH + MD5_CKSUM_LENGTH)) return(KRB5_CRYPTO_INTERNAL); /* create the confounder */ data.length = CONFLENGTH; data.data = (char *) conf; if ((ret = krb5_c_random_make_octets(context, &data))) return(ret); /* hash the confounder, then the input data */ hash_input = (krb5_data *)MALLOC(sizeof(krb5_data) * 2); if (hash_input == NULL) return(KRB5_RC_MALLOC); hash_input[0].data = (char *)conf; hash_input[0].length = CONFLENGTH; hash_input[1].data = input->data; hash_input[1].length = input->length; /* Save the pointer to the beginning of the output buffer */ outptr = (char *)output->data; /* * Move the output ptr ahead so we can write the hash * digest directly into the buffer. */ output->data = output->data + CONFLENGTH; /* Use generic hash function that calls to kEF */ if (k5_ef_hash(context, 2, hash_input, output)) { FREE(hash_input, sizeof(krb5_data) * 2); return(KRB5_KEF_ERROR); } /* restore the original ptr to the output data */ output->data = outptr; /* * Put the confounder in the beginning of the buffer to be * encrypted. */ bcopy(conf, output->data, CONFLENGTH); bcopy(key->contents, xorkey, sizeof(xorkey)); for (i=0; ienctype; newkey.contents = xorkey; newkey.length = sizeof(xorkey); newkey.dk_list = NULL; newkey.kef_key.ck_data = NULL; ret = init_key_kef(context->kef_cipher_mt, &newkey); if (ret) { FREE(hash_input, sizeof(krb5_data) * 2); return (ret); } /* encrypt it, in place. this has a return value, but it's always zero. */ ret = mit_des_cbc_encrypt(context, (krb5_pointer) output->data, (krb5_pointer) output->data, output->length, &newkey, (unsigned char*) mit_des_zeroblock, 1); FREE(hash_input, sizeof(krb5_data) * 2); (void)crypto_destroy_ctx_template(newkey.key_tmpl); return(ret); } /*ARGSUSED*/ static krb5_error_code k5_md5des_verify(krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_const krb5_data *hash, krb5_boolean *valid) { krb5_error_code ret = 0; unsigned char plaintext[CONFLENGTH + MD5_CKSUM_LENGTH]; unsigned char xorkey[8]; int i; int compathash = 0; krb5_octet outtmp[MD5_CKSUM_LENGTH]; size_t hisize; krb5_data *hash_input; krb5_data hash_output; krb5_keyblock newkey; if (key->length != MIT_DES_KEYSIZE) return(KRB5_BAD_KEYSIZE); if (ivec) return(KRB5_CRYPTO_INTERNAL); if (hash->length != (CONFLENGTH + MD5_CKSUM_LENGTH)) { #ifdef KRB5_MD5DES_BETA5_COMPAT if (hash->length != MD5_CKSUM_LENGTH) return(KRB5_CRYPTO_INTERNAL); else compathash = 1; #else return(KRB5_CRYPTO_INTERNAL); #endif } /* create and schedule the encryption key */ (void) bcopy(key->contents, xorkey, sizeof(xorkey)); if (!compathash) { for (i=0; ienctype; newkey.contents = xorkey; newkey.length = sizeof(xorkey); newkey.dk_list = NULL; newkey.kef_key.ck_data = NULL; ret = init_key_kef(context->kef_cipher_mt, &newkey); /* decrypt it. this has a return value, but it's always zero. */ if (!compathash) { ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, (krb5_pointer) plaintext, hash->length, &newkey, (unsigned char*) mit_des_zeroblock, 0); } else { ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, (krb5_pointer) plaintext, hash->length, &newkey, xorkey, 0); } if (ret) goto cleanup; /* hash the confounder, then the input data */ i = 1; if (!compathash) i++; hisize = sizeof(krb5_data) * i; hash_input = (krb5_data *)MALLOC(hisize); if (hash_input == NULL) return(KRB5_RC_MALLOC); i=0; if (!compathash) { hash_input[i].data = (char *)plaintext; hash_input[i].length = CONFLENGTH; i++; } hash_input[i].data = input->data; hash_input[i].length = input->length; hash_output.data = (char *)outtmp; hash_output.length = sizeof(outtmp); if (k5_ef_hash(context, 1, hash_input, &hash_output)) { ret = KRB5_KEF_ERROR; goto cleanup; } /* compare the decrypted hash to the computed one */ if (!compathash) { *valid = !bcmp((const void *)(plaintext+CONFLENGTH), (void *)outtmp, MD5_CKSUM_LENGTH); } else { *valid = !bcmp((const void *)plaintext, (void *)outtmp, MD5_CKSUM_LENGTH); } bzero((void *)plaintext, sizeof(plaintext)); cleanup: if (hash_input != NULL && hisize > 0) FREE(hash_input, hisize); (void)crypto_destroy_ctx_template(newkey.key_tmpl); return(ret); } const struct krb5_keyhash_provider krb5int_keyhash_md5des = { CONFLENGTH+MD5_CKSUM_LENGTH, k5_md5des_hash, k5_md5des_verify }; /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/crypto/keyhash_provider/hmac_md5.c * (I don't know) . * Copyright2001 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. * * * Implementation of the Microsoft hmac-md5 checksum type. * Implemented based on draft-brezak-win2k-krb-rc4-hmac-03 */ #include #include #include #include #include /*ARGSUSED*/ static krb5_error_code k5_hmac_md5_hash (krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *iv, const krb5_data *input, krb5_data *output) { krb5_keyusage ms_usage; krb5_error_code ret; krb5_keyblock ks; krb5_data ds, ks_constant, md5tmp; krb5_data hash_input[2]; int i; char t[4], outbuf[MD5_CKSUM_LENGTH]; #ifdef _KERNEL KRB5_LOG1(KRB5_INFO, "k5_hmac_md5_hash() hash_mt = %ld cipher_mt = %ld", (ulong_t) context->kef_hash_mt, (ulong_t) context->kef_cipher_mt); #endif for (i=0; ienctype) break; } if (i == krb5_enctypes_length) { KRB5_LOG(KRB5_ERR, "krb5_ck_make_checksum bad enctype: %d", key->enctype); return(KRB5_BAD_ENCTYPE); } bzero(&ks, sizeof(krb5_keyblock)); /* * Solaris Kerberos: The digest length is that of MD5_CKSUM_LENGTH not the key * length, as keys can be of varying lengths but should not affect the digest * length. The signing key is the digest and therefore is also the same * length, MD5_CKSUM_LENGTH. */ ds.length = MD5_CKSUM_LENGTH; ds.data = MALLOC(ds.length); if (ds.data == NULL) return (ENOMEM); ks.contents = (void *) ds.data; ks.length = MD5_CKSUM_LENGTH; #ifdef _KERNEL if (key->kef_key.ck_data == NULL) { ret = init_key_kef(krb5_enctypes_list[i].kef_cipher_mt, (krb5_keyblock *)key); if (ret) goto cleanup; } ret = init_key_kef(krb5_enctypes_list[i].kef_cipher_mt, &ks); if (ret) goto cleanup; #endif /* _KERNEL */ ks_constant.data = "signaturekey"; ks_constant.length = strlen(ks_constant.data)+1; /* Including null*/ #ifdef _KERNEL ret = krb5_hmac(context, (krb5_keyblock *)key, &ks_constant, &ds); #else ret = krb5_hmac(context, &krb5int_hash_md5, key, 1, &ks_constant, &ds); #endif /* _KERNEL */ if (ret) goto cleanup; ms_usage = krb5int_arcfour_translate_usage (usage); t[0] = (ms_usage) & 0xff; t[1] = (ms_usage>>8) & 0xff; t[2] = (ms_usage >>16) & 0xff; t[3] = (ms_usage>>24) & 0XFF; hash_input[0].data = (char *)&t; hash_input[0].length = 4; hash_input[1].data = input->data; hash_input[1].length = input->length; md5tmp.data = (void *)outbuf; md5tmp.length = sizeof(outbuf); /* Use generic hash function that calls to kEF */ if (k5_ef_hash(context, 2, hash_input, &md5tmp)) { return (KRB5_KEF_ERROR); } #ifdef _KERNEL ret = krb5_hmac (context, &ks, &md5tmp, output); #else ret = krb5_hmac (context, &krb5int_hash_md5, &ks, 1, &md5tmp, output); #endif /* _KERNEL */ cleanup: bzero(md5tmp.data, md5tmp.length); bzero(ks.contents, ks.length); FREE (ks.contents, ks.length); return (ret); } const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5 = { MD5_CKSUM_LENGTH, k5_hmac_md5_hash, NULL /*checksum again*/ }; /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2025 RackTop Systems, Inc. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "cksumtypes.h" #include "etypes.h" #include "dk.h" krb5_error_code KRB5_CALLCONV krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum) { int i, e1, e2; krb5_data data; krb5_error_code ret = 0; size_t cksumlen; KRB5_LOG0(KRB5_INFO, "krb5_c_make_checksum() start."); for (i=0; ihashsize; else cksumlen = krb5_cksumtypes_list[i].hash->hashsize; #ifdef _KERNEL context->kef_cksum_mt = krb5_cksumtypes_list[i].kef_cksum_mt; #endif cksum->length = cksumlen; if ((cksum->contents = (krb5_octet *) MALLOC(cksum->length)) == NULL) { cksum->length = 0; return(ENOMEM); } data.length = cksum->length; data.data = (char *) cksum->contents; if (krb5_cksumtypes_list[i].keyhash) { /* check if key is compatible */ if (krb5_cksumtypes_list[i].keyed_etype) { for (e1=0; e1enctype) break; /* * Solaris Kerberos: The actual key encryption type could be * arbitrary, so the checksum enc type doesn't need to be the same. */ if ((e1 == krb5_enctypes_length) || (e2 == krb5_enctypes_length)) { ret = KRB5_BAD_ENCTYPE; goto cleanup; } } #ifdef _KERNEL context->kef_cipher_mt = krb5_enctypes_list[e1].kef_cipher_mt; context->kef_hash_mt = krb5_enctypes_list[e1].kef_hash_mt; if (key->kef_key.ck_data == NULL) { if ((ret = init_key_kef(context->kef_cipher_mt, (krb5_keyblock *)key))) goto cleanup; } #else if ((ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key))) goto cleanup; #endif /* _KERNEL */ ret = (*(krb5_cksumtypes_list[i].keyhash->hash))(context, key, usage, 0, input, &data); } else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) { #ifdef _KERNEL context->kef_cipher_mt = get_cipher_mech_type(context, (krb5_keyblock *)key); context->kef_hash_mt = get_hash_mech_type(context, (krb5_keyblock *)key); /* * If the hash_mt is invalid, try using the cksum_mt * because "hash" and "checksum" are overloaded terms * in some places. */ if (context->kef_hash_mt == CRYPTO_MECH_INVALID) context->kef_hash_mt = context->kef_cksum_mt; #else ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key); if (ret) goto cleanup; #endif /* _KERNEL */ ret = krb5_dk_make_checksum(context, krb5_cksumtypes_list[i].hash, key, usage, input, &data); } else { /* * No key is used, hash and cksum are synonymous * in this case */ #ifdef _KERNEL context->kef_hash_mt = context->kef_cksum_mt; #endif /* _KERNEL */ ret = (*(krb5_cksumtypes_list[i].hash->hash))(context, 1, input, &data); } if (!ret) { cksum->magic = KV5M_CHECKSUM; cksum->checksum_type = cksumtype; if (krb5_cksumtypes_list[i].trunc_size) { krb5_octet *trunc; size_t old_len = cksum->length; /* * Solaris Kerberos: * The Kernel does not like 'realloc' (which is what * MIT code does here), so we do our own "realloc". */ cksum->length = krb5_cksumtypes_list[i].trunc_size; trunc = (krb5_octet *) MALLOC(cksum->length); if (trunc) { (void) memcpy(trunc, cksum->contents, cksum->length); FREE(cksum->contents, old_len); cksum->contents = trunc; } else { ret = ENOMEM; } } } cleanup: if (ret) { (void) memset(cksum->contents, 0, cksum->length); FREE(cksum->contents, cksum->length); cksum->length = 0; cksum->contents = NULL; } KRB5_LOG(KRB5_INFO, "krb5_c_make_checksum() end ret = %d\n", ret); return(ret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 2003 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. */ #include "k5-int.h" #include "etypes.h" /*ARGSUSED*/ krb5_error_code krb5int_c_mandatory_cksumtype (krb5_context ctx, krb5_enctype etype, krb5_cksumtype *cksumtype) { int i; for (i = 0; i < krb5_enctypes_length; i++) if (krb5_enctypes_list[i].etype == etype) { *cksumtype = krb5_enctypes_list[i].required_ctype; return 0; } return KRB5_BAD_ENCTYPE; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" /* * Solaris Kerberos defines memory management macros in , * which is included by , so we need not include */ /* #include */ /* n-fold(k-bits): l = lcm(n,k) r = l/k s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) compute the 1's complement sum: n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] */ /* representation: msb first, assume n and k are multiples of 8, and that k>=16. this is the case of all the cryptosystems which are likely to be used. this function can be replaced if that assumption ever fails. */ /* input length is in bits */ void krb5_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits, unsigned char *out) { int a,b,c,lcm; int byte, i, msbit; /* the code below is more readable if I make these bytes instead of bits */ inbits >>= 3; outbits >>= 3; /* first compute lcm(n,k) */ a = outbits; b = inbits; while(b != 0) { c = b; b = a%b; a = c; } lcm = outbits*inbits/a; /* now do the real work */ (void) memset(out, 0, outbits); byte = 0; /* this will end up cycling through k lcm(k,n)/k times, which is correct */ for (i=lcm-1; i>=0; i--) { /* compute the msbit in k which gets added into this byte */ msbit = (/* first, start with the msbit in the first, unrotated byte */ ((inbits<<3)-1) /* then, for each byte, shift to the right for each repetition */ +(((inbits<<3)+13)*(i/inbits)) /* last, pick out the correct byte within that shifted repetition */ +((inbits-(i%inbits))<<3) )%(inbits<<3); /* pull out the byte value itself */ byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| (in[((inbits)-(msbit>>3))%inbits])) >>((msbit&7)+1))&0xff; /* do the addition */ byte += out[i%outbits]; out[i%outbits] = byte&0xff; #if 0 printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit, (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| (in[((inbits)-(msbit>>3))%inbits])) >>((msbit&7)+1))&0xff, byte); #endif /* keep around the carry bit, if any */ byte >>= 8; #if 0 printf("carry=%d\n", byte); #endif } /* if there's a carry bit left over, add it back in */ if (byte) { for (i=outbits-1; i>=0; i--) { /* do the addition */ byte += out[i]; out[i] = byte&0xff; /* keep around the carry bit, if any */ byte >>= 8; } } } /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "old.h" /*ARGSUSED*/ krb5_error_code krb5_old_decrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output) { krb5_error_code ret; size_t blocksize, hashsize, plainsize; unsigned char *cn; krb5_data output, cksum, crcivec; int alloced; unsigned char orig_cksum[128], new_cksum[128]; blocksize = enc->block_size; hashsize = hash->hashsize; /* Verify input and output lengths. */ if (input->length < blocksize + hashsize || input->length % blocksize != 0) return(KRB5_BAD_MSIZE); plainsize = input->length - blocksize - hashsize; if (arg_output->length < plainsize) return(KRB5_BAD_MSIZE); if (arg_output->length < input->length) { output.length = input->length; if ((output.data = (char *) MALLOC(output.length)) == NULL) { return(ENOMEM); } alloced = 1; } else { output.length = input->length; output.data = arg_output->data; alloced = 0; } /* decrypt it */ /* save last ciphertext block in case we decrypt in place */ if (ivec != NULL && ivec->length == blocksize) { cn = MALLOC(blocksize); if (cn == NULL) { ret = ENOMEM; goto cleanup; } (void) memcpy(cn, input->data + input->length - blocksize, blocksize); } else cn = NULL; /* XXX this is gross, but I don't have much choice */ if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { crcivec.length = key->length; crcivec.data = (char *) key->contents; ivec = &crcivec; } if ((ret = ((*(enc->decrypt))(context, key, ivec, input, &output)))) goto cleanup; /* verify the checksum */ (void) memcpy(orig_cksum, output.data+blocksize, hashsize); (void) memset(output.data+blocksize, 0, hashsize); cksum.length = hashsize; cksum.data = (char *)new_cksum; if ((ret = ((*(hash->hash))(context, 1, &output, &cksum)))) goto cleanup; if (memcmp(cksum.data, orig_cksum, cksum.length) != 0) { ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto cleanup; } /* copy the plaintext around */ if (alloced) { (void) memcpy(arg_output->data, output.data+blocksize+hashsize, plainsize); } else { (void) memmove(arg_output->data, arg_output->data+blocksize+hashsize, plainsize); } arg_output->length = plainsize; /* update ivec */ if (cn != NULL) (void) memcpy(ivec->data, cn, blocksize); ret = 0; cleanup: if (alloced) { (void) memset(output.data, 0, output.length); FREE(output.data, output.length); } if (cn != NULL) FREE(cn, blocksize); (void) memset(new_cksum, 0, hashsize); return(ret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "old.h" void krb5_old_encrypt_length(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t inputlen, size_t *length) { size_t blocksize, hashsize; blocksize = enc->block_size; hashsize = hash->hashsize; *length = krb5_roundup(blocksize+hashsize+inputlen, blocksize); } /*ARGSUSED*/ krb5_error_code krb5_old_encrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret; size_t blocksize, hashsize, enclen; krb5_data datain, crcivec; int real_ivec; blocksize = enc->block_size; hashsize = hash->hashsize; krb5_old_encrypt_length(enc, hash, input->length, &enclen); if (output->length < enclen) return(KRB5_BAD_MSIZE); output->length = enclen; /* fill in confounded, padded, plaintext buffer with zero checksum */ (void) memset(output->data, 0, output->length); datain.length = blocksize; datain.data = (char *) output->data; if ((ret = krb5_c_random_make_octets(context, &datain))) return(ret); (void) memcpy(output->data+blocksize+hashsize, input->data, input->length); /* compute the checksum */ datain.length = hashsize; datain.data = output->data+blocksize; if ((ret = ((*(hash->hash))(context, 1, output, &datain)))) goto cleanup; /* encrypt it */ /* XXX this is gross, but I don't have much choice */ if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { crcivec.length = key->length; crcivec.data = (char *) key->contents; ivec = &crcivec; real_ivec = 0; } else real_ivec = 1; if ((ret = ((*(enc->encrypt))(context, key, ivec, output, output)))) goto cleanup; /* update ivec */ if (real_ivec && ivec != NULL && ivec->length == blocksize) (void) memcpy(ivec->data, output->data + output->length - blocksize, blocksize); cleanup: if (ret) (void) memset(output->data, 0, output->length); return(ret); } /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #include #ifdef _KERNEL #include #endif #ifndef _KERNEL /* * Solaris kerberos: we don't need a random number generator * for the /dev/[u]random, as it uses entropy in the kernel. * Keep this function as some apps might call it directly. */ /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_random_seed(krb5_context context, krb5_data *data) { /* * We can't do much if this fails, so ignore the * return code. /dev/urandom has its own entropy * source, so seeding it from here is of questionable * value in the first place. */ (void) C_SeedRandom(krb_ctx_hSession(context), (CK_BYTE_PTR)data->data, (CK_ULONG)data->length); return(0); } #endif /* !_KERNEL */ /* * krb5_get_random_octets * New for Solaris 9. This routine takes advantage of the new * /dev/[u]random interface provided in Solaris 9 for getting random * bytes generated from the kernel. The entropy produced there is generally * considered better than the current MIT PRNG code that we are replacing. * * This func is visible so that it can be used to generate a * random confounder. */ #ifndef _KERNEL #endif /* ! _KERNEL */ /* * We can assume that the memory for data is already malloc'd. * Return an error if there is an error, but don't clear the data->length * or free data->data. This will be done by the calling function. */ /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_c_random_make_octets(krb5_context context, krb5_data *data) { /* * Solaris kerberos uses /dev/[u]random */ #ifndef _KERNEL /* User space code */ krb5_error_code err = 0; CK_RV rv; KRB5_LOG0(KRB5_INFO, "krb5_c_random_make_octets() start, user space using " "krb5_get_random_octets()\n"); rv = C_GenerateRandom(krb_ctx_hSession(context), (CK_BYTE_PTR)data->data, (CK_ULONG)data->length); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_GenerateRandom failed in " "krb5_c_random_make_octets: rv = 0x%x.", rv); err = PKCS_ERR; } if (err != 0) { KRB5_LOG0(KRB5_ERR, "krb5_c_random_make_octets() end, error"); return (err); } #else /* Kernel code section */ /* * Solaris Kerberos: for kernel code we use the randomness generator native * to Solaris 9. We avoid global variables and other nastiness this way. * * Using random_get_pseudo_bytes() instead of random_get_bytes() because it * will not return an error code if there isn't enough entropy but will use * a pseudo random algorithm to produce randomness. Most of the time it * should be as good as random_get_bytes() and we don't have to worry about * dealing with a non-fatal error. */ KRB5_LOG0(KRB5_INFO, "krb5_c_random_make_octets() start, kernel using " "random_get_pseudo_bytes()\n "); if(random_get_pseudo_bytes((uint8_t *)data->data, data->length) != 0) { KRB5_LOG0(KRB5_ERR, "krb5_c_random_make_octets() end, " "random_get_pseudo_bytes() error.\n"); return(KRB5_CRYPTO_INTERNAL); } #endif /* !_KERNEL */ KRB5_LOG0(KRB5_INFO, "krb5_c_random_make_octets() end\n"); return(0); } /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "raw.h" /*ARGSUSED*/ krb5_error_code krb5_raw_decrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { if (output->length < input->length) return KRB5_BAD_MSIZE; return((*(enc->decrypt))(context, key, ivec, input, output)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "raw.h" /*ARGSUSED*/ void krb5_raw_encrypt_length(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t inputlen, size_t *length) { size_t blocksize; blocksize = enc->block_size; *length = krb5_roundup(inputlen, blocksize); } /*ARGSUSED*/ krb5_error_code krb5_raw_encrypt(krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { return((*(enc->encrypt))(context, key, ivec, input, output)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" #include "cksumtypes.h" krb5_error_code KRB5_CALLCONV krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid) { int i; size_t hashsize; krb5_error_code ret; krb5_data indata; krb5_checksum computed; for (i=0; ichecksum_type) break; } if (i == krb5_cksumtypes_length) return(KRB5_BAD_ENCTYPE); /* if there's actually a verify function, call it */ indata.length = cksum->length; indata.data = (char *) cksum->contents; *valid = 0; if (krb5_cksumtypes_list[i].keyhash && krb5_cksumtypes_list[i].keyhash->verify) return((*(krb5_cksumtypes_list[i].keyhash->verify))( context, key, usage, 0, data, &indata, valid)); /* otherwise, make the checksum again, and compare */ if ((ret = krb5_c_checksum_length(context, cksum->checksum_type, &hashsize))) return(ret); if (cksum->length != hashsize) return(KRB5_BAD_MSIZE); computed.length = hashsize; if ((ret = krb5_c_make_checksum(context, cksum->checksum_type, key, usage, data, &computed))) { FREE(computed.contents, computed.length); return(ret); } *valid = (memcmp(computed.contents, cksum->contents, hashsize) == 0); FREE(computed.contents, computed.length); return(0); } extern krb5_error_code krb5int_aes_string_to_key (krb5_context context, const struct krb5_enc_provider *, const krb5_data *, const krb5_data *, const krb5_data *, krb5_keyblock *key); /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef ARCFOUR_H #define ARCFOUR_H #define CONFOUNDERLENGTH 8 extern void krb5_arcfour_encrypt_length(const struct krb5_enc_provider *, const struct krb5_hash_provider *, size_t, size_t *); extern krb5_error_code krb5_arcfour_encrypt(krb5_context, const struct krb5_enc_provider *, const struct krb5_hash_provider *, const krb5_keyblock *, krb5_keyusage, const krb5_data *, const krb5_data *, krb5_data *); extern krb5_error_code krb5_arcfour_decrypt(krb5_context, const struct krb5_enc_provider *, const struct krb5_hash_provider *, const krb5_keyblock *, krb5_keyusage, const krb5_data *, const krb5_data *, krb5_data *); #ifndef _KERNEL extern krb5_error_code krb5int_arcfour_string_to_key( krb5_context, const struct krb5_enc_provider *, const krb5_data *, const krb5_data *, const krb5_data *, krb5_keyblock *); #endif /* _KERNEL */ extern const struct krb5_enc_provider krb5int_enc_arcfour; krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); #endif /* ARCFOUR_H */ #ifndef KRB5_AUTH_CONTEXT #define KRB5_AUTH_CONTEXT struct _krb5_auth_context { krb5_magic magic; krb5_address * remote_addr; krb5_address * remote_port; krb5_address * local_addr; krb5_address * local_port; krb5_keyblock * keyblock; krb5_keyblock * send_subkey; krb5_keyblock * recv_subkey; krb5_int32 auth_context_flags; krb5_ui_4 remote_seq_number; krb5_ui_4 local_seq_number; krb5_authenticator *authentp; /* mk_req, rd_req, mk_rep, ...*/ krb5_cksumtype req_cksumtype; /* mk_safe, ... */ krb5_cksumtype safe_cksumtype; /* mk_safe, ... */ krb5_pointer i_vector; /* mk_priv, rd_priv only */ krb5_rcache rcache; krb5_enctype * permitted_etypes; /* rd_req */ krb5_mk_req_checksum_func checksum_func; void *checksum_func_data; }; /* Internal auth_context_flags */ #define KRB5_AUTH_CONN_INITIALIZED 0x00010000 #define KRB5_AUTH_CONN_USED_W_MK_REQ 0x00020000 #define KRB5_AUTH_CONN_USED_W_RD_REQ 0x00040000 #define KRB5_AUTH_CONN_SANE_SEQ 0x00080000 #define KRB5_AUTH_CONN_HEIMDAL_SEQ 0x00100000 #endif /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" extern const struct krb5_cksumtypes krb5_cksumtypes_list[]; extern const int krb5_cksumtypes_length; /* * include/krb5/crc-32.h * * Copyright 1989,1990 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. * * * Definitions for the CRC-32 checksum */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef KRB5_CRC32__ #define KRB5_CRC32__ #define CRC32_CKSUM_LENGTH 4 void mit_crc32 (const krb5_pointer in, size_t in_length, unsigned long *c); #ifdef CRC32_SHIFT4 void mit_crc32_shift4(const krb5_pointer /* in */, const size_t /* in_length */, unsigned long * /* cksum */); #endif #endif /* KRB5_CRC32__ */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/crypto/des/des_int.h * * Copyright 1987, 1988, 1990, 2002 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. * * * Private include file for the Data Encryption Standard library. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* only do the whole thing once */ #ifndef DES_INTERNAL_DEFS #define DES_INTERNAL_DEFS #include "k5-int.h" /* * Begin "mit-des.h" */ #ifndef KRB5_MIT_DES__ #define KRB5_MIT_DES__ #if 0 /* SUNW14resync */ #define KRB5INT_CRYPTO_DES_INT /* skip krb4-specific DES stuff */ #include "kerberosIV/des.h" /* for des_key_schedule, etc. */ #undef KRB5INT_CRYPTO_DES_INT /* don't screw other inclusions of des.h */ #endif /* * SUNW14resync * Solaris Kerberos does not do krb4 so we don't have its des.h file * but we need a few symbols from it so we include them here. */ /* begin: from mit kerberosIV/des.h */ #if UINT_MAX >= 0xFFFFFFFFUL #define DES_INT32 int #define DES_UINT32 unsigned int #else #define DES_INT32 long #define DES_UINT32 unsigned long #endif /* end: from mit kerberosIV/des.h */ typedef unsigned char des_cblock[8]; /* crypto-block size */ typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16]; typedef des_cblock mit_des_cblock; typedef des_key_schedule mit_des_key_schedule; /* Triple-DES structures */ typedef mit_des_cblock mit_des3_cblock[3]; typedef mit_des_key_schedule mit_des3_key_schedule[3]; #define MIT_DES_ENCRYPT 1 #define MIT_DES_DECRYPT 0 #define K5ROUNDUP(x, align) (-(-(x) & -(align))) /* the first byte of the key is already in the keyblock */ #define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet)) #define MIT_DES_CBC_CRC_PAD_MINIMUM CRC32_CKSUM_LENGTH /* This used to be 8*sizeof(krb5_octet) */ #define MIT_DES_KEYSIZE 8 #define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet)) /* * Check if k5-int.h has been included before us. If so, then check to see * that our view of the DES key size is the same as k5-int.h's. */ #ifdef KRB5_MIT_DES_KEYSIZE #if MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE) #endif /* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */ #endif /* KRB5_MIT_DES_KEYSIZE */ #endif /* KRB5_MIT_DES__ */ /* * End "mit-des.h" */ #ifndef _KERNEL /* afsstring2key.c */ extern krb5_error_code mit_afs_string_to_key (krb5_context context, krb5_keyblock *keyblock, const krb5_data *data, const krb5_data *salt); #endif /* f_cksum.c */ extern unsigned long mit_des_cbc_cksum ( krb5_context context, const krb5_octet *, krb5_octet *, unsigned long , krb5_keyblock *, const krb5_octet *); /* f_cbc.c */ extern int mit_des_cbc_encrypt (krb5_context context, const mit_des_cblock *in, mit_des_cblock *out, long length, krb5_keyblock *key, mit_des_cblock ivec, int encrypt); #define mit_des_zeroblock krb5int_c_mit_des_zeroblock extern const mit_des_cblock mit_des_zeroblock; /* fin_rndkey.c */ extern krb5_error_code mit_des_finish_random_key ( const krb5_encrypt_block *, krb5_pointer *); /* finish_key.c */ extern krb5_error_code mit_des_finish_key ( krb5_encrypt_block *); /* key_parity.c */ extern void mit_des_fixup_key_parity (mit_des_cblock ); extern int mit_des_check_key_parity (mit_des_cblock ); /* process_ky.c */ extern krb5_error_code mit_des_process_key ( krb5_encrypt_block *, const krb5_keyblock *); /* string2key.c */ extern krb5_error_code mit_des_string_to_key ( const krb5_encrypt_block *, krb5_keyblock *, const krb5_data *, const krb5_data *); /* weak_key.c */ extern int mit_des_is_weak_key (mit_des_cblock ); /* cmb_keys.c */ krb5_error_code mit_des_combine_subkeys (const krb5_keyblock *, const krb5_keyblock *, krb5_keyblock **); /* f_pcbc.c */ int mit_des_pcbc_encrypt (); /* f_sched.c */ int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule); /* misc.c */ extern void swap_bits (char *); extern unsigned long long_swap_bits (unsigned long ); extern unsigned long swap_six_bits_to_ansi (unsigned long ); extern unsigned long swap_four_bits_to_ansi (unsigned long ); extern unsigned long swap_bit_pos_1 (unsigned long ); extern unsigned long swap_bit_pos_0 (unsigned long ); extern unsigned long swap_bit_pos_0_to_ansi (unsigned long ); extern unsigned long rev_swap_bit_pos_0 (unsigned long ); extern unsigned long swap_byte_bits (unsigned long ); extern unsigned long swap_long_bytes_bit_number (unsigned long ); #ifdef FILE /* XXX depends on FILE being a #define! */ extern void test_set (FILE *, const char *, int, const char *, int); #endif /* d3_cbc.c */ extern int mit_des3_cbc_encrypt (krb5_context context, const mit_des_cblock *in, mit_des_cblock *out, unsigned long length, krb5_keyblock *key, const mit_des_cblock ivec, int enc); /* d3_procky.c */ extern krb5_error_code mit_des3_process_key (krb5_encrypt_block * eblock, const krb5_keyblock * keyblock); /* d3_str2ky.c */ extern krb5_error_code mit_des3_string_to_key (const krb5_encrypt_block * eblock, krb5_keyblock * keyblock, const krb5_data * data, const krb5_data * salt); /* u_nfold.c */ extern krb5_error_code mit_des_n_fold (const krb5_octet * input, const size_t in_len, krb5_octet * output, const size_t out_len); extern krb5_error_code mit_des_set_random_sequence_number (const krb5_data * sequence, krb5_pointer random_state); #endif /*DES_INTERNAL_DEFS*/ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" void krb5_dk_encrypt_length (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t input, size_t *length); krb5_error_code krb5_dk_encrypt ( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); extern krb5_error_code krb5_dk_decrypt (krb5_context context, krb5_const struct krb5_enc_provider *enc, krb5_const struct krb5_hash_provider *hash, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *arg_output); extern krb5_error_code krb5_derive_key (krb5_context context, krb5_const struct krb5_enc_provider *enc, krb5_const krb5_keyblock *inkey, krb5_keyblock *outkey, krb5_const krb5_data *in_constant); extern krb5_error_code krb5_dk_make_checksum (krb5_context context, krb5_const struct krb5_hash_provider *hash, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *input, krb5_data *output); #ifndef _KERNEL extern krb5_error_code krb5int_dk_string_to_key (krb5_context context, krb5_const struct krb5_enc_provider *enc, krb5_const krb5_data *string, krb5_const krb5_data *salt, krb5_const krb5_data *params, krb5_keyblock *key); #endif void krb5int_aes_encrypt_length (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t input, size_t *length); krb5_error_code krb5int_aes_dk_encrypt ( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); krb5_error_code krb5int_aes_dk_decrypt ( krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); extern krb5_error_code krb5int_aes_string_to_key (krb5_context context, const struct krb5_enc_provider *, const krb5_data *, const krb5_data *, const krb5_data *, krb5_keyblock *key); /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" extern const struct krb5_enc_provider krb5int_enc_des; extern const struct krb5_enc_provider krb5int_enc_des3; extern const struct krb5_enc_provider krb5int_enc_arcfour; extern const struct krb5_enc_provider krb5int_enc_aes128; extern const struct krb5_enc_provider krb5int_enc_aes256; /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" extern struct krb5_keytypes krb5_enctypes_list[]; extern const int krb5_enctypes_length; /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GSSAPIP_GENERIC_H_ #define _GSSAPIP_GENERIC_H_ /* * $Id: gssapiP_generic.h 18396 2006-07-25 20:29:43Z lxs $ */ #if defined(_WIN32) #include "k5-int.h" #else #include "autoconf.h" #ifndef _KERNEL #ifdef HAVE_STDLIB_H #include #endif /* !_KERNEL */ #endif #endif #include "k5-thread.h" #include "gssapi_generic.h" #include "gssapi_err_generic.h" #ifndef _KERNEL #include #else #include #endif /* !_KERNEL */ #include "k5-platform.h" typedef UINT64_TYPE gssint_uint64; #include "gssapi/gssapi_ext.h" /** helper macros **/ #if 0 /* SUNW15resync - on Solaris g_OID_equal is in gssapi_ext.h */ #define g_OID_equal(o1, o2) \ (((o1)->length == (o2)->length) && \ (memcmp((o1)->elements,(o2)->elements,(unsigned int) (o1)->length) == 0)) #endif /* this code knows that an int on the wire is 32 bits. The type of num should be at least this big, or the extra shifts may do weird things */ #define TWRITE_INT(ptr, num, bigend) \ (ptr)[0] = (char) ((bigend)?((num)>>24):((num)&0xff)); \ (ptr)[1] = (char) ((bigend)?(((num)>>16)&0xff):(((num)>>8)&0xff)); \ (ptr)[2] = (char) ((bigend)?(((num)>>8)&0xff):(((num)>>16)&0xff)); \ (ptr)[3] = (char) ((bigend)?((num)&0xff):((num)>>24)); \ (ptr) += 4; #define TWRITE_INT16(ptr, num, bigend) \ (ptr)[0] = (char) ((bigend)?((num)>>24):((num)&0xff)); \ (ptr)[1] = (char) ((bigend)?(((num)>>16)&0xff):(((num)>>8)&0xff)); \ (ptr) += 2; #define TREAD_INT(ptr, num, bigend) \ (num) = (((ptr)[0]<<((bigend)?24: 0)) | \ ((ptr)[1]<<((bigend)?16: 8)) | \ ((ptr)[2]<<((bigend)? 8:16)) | \ ((ptr)[3]<<((bigend)? 0:24))); \ (ptr) += 4; #define TREAD_INT16(ptr, num, bigend) \ (num) = (((ptr)[0]<<((bigend)?24: 0)) | \ ((ptr)[1]<<((bigend)?16: 8))); \ (ptr) += 2; #define TWRITE_STR(ptr, str, len) \ (void) memcpy((ptr), (char *) (str), (len)); \ (ptr) += (len); #define TREAD_STR(ptr, str, len) \ (str) = (ptr); \ (ptr) += (len); #define TWRITE_BUF(ptr, buf, bigend) \ TWRITE_INT((ptr), (buf).length, (bigend)); \ TWRITE_STR((ptr), (buf).value, (buf).length); /** malloc wrappers; these may actually do something later */ #ifdef _KERNEL #define xmalloc(n) MALLOC(n) #else #define xmalloc(n) malloc(n) #endif #define xrealloc(p,n) realloc(p,n) #ifdef xfree #undef xfree #endif #ifdef _KERNEL #define xfree_wrap(p,sze) kmem_free(p,sze) #else #define xfree_wrap(p,sze) free(p) #define xfree(p) free(p) #endif /** 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_save_lucidctx_id gssint_g_save_lucidctx_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_validate_lucidctx_id gssint_g_validate_lucidctx_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_delete_lucidctx_id gssint_g_delete_lucidctx_id #define g_make_string_buffer gssint_g_make_string_buffer #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_elt *g_set_elt; typedef struct { k5_mutex_t mutex; void *data; } g_set; #define G_SET_INIT { K5_MUTEX_PARTIAL_INITIALIZER, 0 } int g_set_init (g_set_elt *s); int g_set_destroy (g_set_elt *s); int g_set_entry_add (g_set_elt *s, void *key, void *value); int g_set_entry_delete (g_set_elt *s, void *key); int g_set_entry_get (g_set_elt *s, void *key, void **value); int g_save_name (g_set *vdb, gss_name_t name); int g_save_cred_id (g_set *vdb, gss_cred_id_t cred); int g_save_ctx_id (g_set *vdb, gss_ctx_id_t ctx); int g_save_lucidctx_id (g_set *vdb, void *lctx); int g_validate_name (g_set *vdb, gss_name_t name); int g_validate_cred_id (g_set *vdb, gss_cred_id_t cred); int g_validate_ctx_id (g_set *vdb, gss_ctx_id_t ctx); int g_validate_lucidctx_id (g_set *vdb, void *lctx); int g_delete_name (g_set *vdb, gss_name_t name); int g_delete_cred_id (g_set *vdb, gss_cred_id_t cred); int g_delete_ctx_id (g_set *vdb, gss_ctx_id_t ctx); int g_delete_lucidctx_id (g_set *vdb, void *lctx); int g_make_string_buffer (const char *str, gss_buffer_t buffer); unsigned int g_token_size (const gss_OID_desc * mech, unsigned int body_size); void g_make_token_header (const gss_OID_desc * mech, unsigned int body_size, unsigned char **buf, int tok_type); gss_int32 g_verify_token_header (const gss_OID_desc * mech, unsigned int *body_size, unsigned char **buf, int tok_type, unsigned int toksize_in, int wrapper_required); OM_uint32 g_display_major_status (OM_uint32 *minor_status, OM_uint32 status_value, OM_uint32 *message_context, gss_buffer_t status_string); OM_uint32 g_display_com_err_status (OM_uint32 *minor_status, OM_uint32 status_value, gss_buffer_t status_string); gss_int32 g_order_init (void **queue, gssint_uint64 seqnum, int do_replay, int do_sequence, int wide); gss_int32 g_order_check (void **queue, gssint_uint64 seqnum); void g_order_free (void **queue); gss_uint32 g_queue_size(void *vqueue, size_t *sizep); gss_uint32 g_queue_externalize(void *vqueue, unsigned char **buf, size_t *lenremain); gss_uint32 g_queue_internalize(void **vqueue, unsigned char **buf, size_t *lenremain); char *g_strdup (char *str); /** declarations of internal name mechanism functions **/ #if 0 /* SUNW15resync - mved to mglueP.h for sake of non-krb5 mechs */ OM_uint32 generic_gss_release_buffer (OM_uint32*, /* minor_status */ gss_buffer_t /* buffer */ ); OM_uint32 generic_gss_release_oid_set (OM_uint32*, /* minor_status */ gss_OID_set* /* set */ ); OM_uint32 generic_gss_release_oid (OM_uint32*, /* minor_status */ gss_OID* /* set */ ); OM_uint32 generic_gss_copy_oid (OM_uint32 *, /* minor_status */ gss_OID_desc * const, /* oid */ /* SUNW15resync */ gss_OID * /* new_oid */ ); OM_uint32 generic_gss_create_empty_oid_set (OM_uint32 *, /* minor_status */ gss_OID_set * /* oid_set */ ); OM_uint32 generic_gss_add_oid_set_member (OM_uint32 *, /* minor_status */ const gss_OID_desc * const, /* member_oid */ gss_OID_set * /* oid_set */ ); OM_uint32 generic_gss_test_oid_set_member (OM_uint32 *, /* minor_status */ const gss_OID_desc * const, /* member */ gss_OID_set, /* set */ int * /* present */ ); OM_uint32 generic_gss_oid_to_str (OM_uint32 *, /* minor_status */ const gss_OID_desc * const, /* oid */ gss_buffer_t /* oid_str */ ); OM_uint32 generic_gss_str_to_oid (OM_uint32 *, /* minor_status */ gss_buffer_t, /* oid_str */ gss_OID * /* oid */ ); OM_uint32 generic_gss_oid_compose( OM_uint32 *, /* minor_status */ const char *, /* prefix */ size_t, /* prefix_len */ int, /* suffix */ gss_OID_desc *); /* oid */ OM_uint32 generic_gss_oid_decompose( OM_uint32 *, /* minor_status */ const char *, /*prefix */ size_t, /* prefix_len */ gss_OID_desc *, /* oid */ int *); /* suffix */ #endif /* 0 */ #ifndef _KERNEL int gssint_mecherrmap_init(void); void gssint_mecherrmap_destroy(void); OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc *oid); int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, OM_uint32 *mech_minor); OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode); #endif #endif /* _GSSAPIP_GENERIC_H_ */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * 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 * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GSSAPIP_KRB5_H_ #define _GSSAPIP_KRB5_H_ #include #ifdef HAVE_MEMORY_H #include #endif /* work around sunos braindamage */ #ifdef major #undef major #endif #ifdef minor #undef minor #endif #include "gssapiP_generic.h" /* The include of gssapi_krb5.h will dtrt with the above #defines in * effect. */ #include "gssapi_krb5.h" #include "gssapi_err_krb5.h" #include "gssapi_ext.h" /* for debugging */ #undef CFX_EXERCISE /** constants **/ #define GSS_MECH_KRB5_OID_LENGTH 9 #define GSS_MECH_KRB5_OID "\052\206\110\206\367\022\001\002\002" #define GSS_MECH_KRB5_OLD_OID_LENGTH 5 #define GSS_MECH_KRB5_OLD_OID "\053\005\001\005\002" /* Incorrect krb5 mech OID emitted by MS. */ #define GSS_MECH_KRB5_WRONG_OID_LENGTH 9 #define GSS_MECH_KRB5_WRONG_OID "\052\206\110\202\367\022\001\002\002" #define CKSUMTYPE_KG_CB 0x8003 #define KG_TOK_CTX_AP_REQ 0x0100 #define KG_TOK_CTX_AP_REP 0x0200 #define KG_TOK_CTX_ERROR 0x0300 #define KG_TOK_SIGN_MSG 0x0101 #define KG_TOK_SEAL_MSG 0x0201 #define KG_TOK_MIC_MSG 0x0101 #define KG_TOK_WRAP_MSG 0x0201 #define KG_TOK_DEL_CTX 0x0102 #define KG2_TOK_INITIAL 0x0101 #define KG2_TOK_RESPONSE 0x0202 #define KG2_TOK_MIC 0x0303 #define KG2_TOK_WRAP_INTEG 0x0404 #define KG2_TOK_WRAP_PRIV 0x0505 #define KRB5_GSS_FOR_CREDS_OPTION 1 #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; */ 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; */ SEAL_ALG_DES3KD = 0x0002 }; /* for 3DES */ #define KG_USAGE_SEAL 22 #define KG_USAGE_SIGN 23 #define KG_USAGE_SEQ 24 /* for draft-ietf-krb-wg-gssapi-cfx-01 */ #define KG_USAGE_ACCEPTOR_SEAL 22 #define KG_USAGE_ACCEPTOR_SIGN 23 #define KG_USAGE_INITIATOR_SEAL 24 #define KG_USAGE_INITIATOR_SIGN 25 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; typedef struct _krb5_gss_cred_id_rec { /* protect against simultaneous accesses */ k5_mutex_t lock; /* name/type of credential */ gss_cred_usage_t usage; krb5_principal princ; /* this is not interned as a gss_name_t */ int prerfc_mech; int rfc_mech; /* keytab (accept) data */ krb5_keytab keytab; krb5_rcache rcache; /* ccache (init) data */ krb5_ccache ccache; krb5_timestamp tgt_expire; krb5_enctype *req_enctypes; /* limit negotiated enctypes to this list */ } krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; typedef struct _krb5_gss_ctx_id_rec { unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */ unsigned int established : 1; unsigned int big_endian : 1; unsigned int have_acceptor_subkey : 1; unsigned int seed_init : 1; /* XXX tested but never actually set */ OM_uint32 gss_flags; unsigned char seed[16]; krb5_principal here; krb5_principal there; krb5_keyblock *subkey; int signalg; size_t cksum_size; int sealalg; krb5_keyblock *enc; krb5_keyblock *seq; krb5_timestamp endtime; krb5_ticket_times krb_times; krb5_flags krb_flags; /* XXX these used to be signed. the old spec is inspecific, and the new spec specifies unsigned. I don't believe that the change affects the wire encoding. */ gssint_uint64 seq_send; gssint_uint64 seq_recv; void *seqstate; krb5_context k5_context; krb5_auth_context auth_context; gss_OID_desc *mech_used; /* Protocol spec revision 0 => RFC 1964 with 3DES and RC4 enhancements 1 => draft-ietf-krb-wg-gssapi-cfx-01 No others defined so far. */ int proto; krb5_cksumtype cksumtype; /* for "main" subkey */ krb5_keyblock *acceptor_subkey; /* CFX only */ krb5_cksumtype acceptor_subkey_cksumtype; int cred_rcache; /* did we get rcache from creds? */ krb5_authdata **authdata; } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; extern g_set kg_vdb; extern k5_mutex_t gssint_krb5_keytab_lock; /* helper macros */ #define kg_save_name(name) g_save_name(&kg_vdb,name) #define kg_save_cred_id(cred) g_save_cred_id(&kg_vdb,cred) #define kg_save_ctx_id(ctx) g_save_ctx_id(&kg_vdb,ctx) #define kg_save_lucidctx_id(lctx) g_save_lucidctx_id(&kg_vdb,lctx) #define kg_validate_name(name) g_validate_name(&kg_vdb,name) #define kg_validate_cred_id(cred) g_validate_cred_id(&kg_vdb,cred) #define kg_validate_ctx_id(ctx) g_validate_ctx_id(&kg_vdb,ctx) #define kg_validate_lucidctx_id(lctx) g_validate_lucidctx_id(&kg_vdb,lctx) #define kg_delete_name(name) g_delete_name(&kg_vdb,name) #define kg_delete_cred_id(cred) g_delete_cred_id(&kg_vdb,cred) #define kg_delete_ctx_id(ctx) g_delete_ctx_id(&kg_vdb,ctx) #define kg_delete_lucidctx_id(lctx) g_delete_lucidctx_id(&kg_vdb,lctx) /** helper functions **/ OM_uint32 kg_get_defcred (OM_uint32 *minor_status, gss_cred_id_t *cred); krb5_error_code kg_checksum_channel_bindings (krb5_context context, gss_channel_bindings_t cb, krb5_checksum *cksum, int bigend); krb5_error_code kg_make_seq_num (krb5_context context, krb5_keyblock *key, int direction, krb5_ui_4 seqnum, unsigned char *cksum, unsigned char *buf); krb5_error_code kg_get_seq_num (krb5_context context, krb5_keyblock *key, unsigned char *cksum, unsigned char *buf, int *direction, krb5_ui_4 *seqnum); krb5_error_code kg_make_seed (krb5_context context, krb5_keyblock *key, unsigned char *seed); int kg_confounder_size (krb5_context context, krb5_keyblock *key); krb5_error_code kg_make_confounder (krb5_context context, krb5_keyblock *key, unsigned char *buf); krb5_error_code kg_encrypt (krb5_context context, krb5_keyblock *key, int usage, krb5_pointer iv, krb5_const_pointer in, krb5_pointer out, unsigned int length); krb5_error_code kg_arcfour_docrypt (krb5_context, const krb5_keyblock *longterm_key , int ms_usage, const unsigned char *kd_data, size_t kd_data_len, const unsigned char *input_buf, size_t input_len, unsigned char *output_buf); krb5_error_code kg_decrypt (krb5_context context, krb5_keyblock *key, int usage, krb5_pointer iv, krb5_const_pointer in, krb5_pointer out, unsigned int length); OM_uint32 kg_seal (OM_uint32 *minor_status, gss_ctx_id_t context_handle, int conf_req_flag, int qop_req, gss_buffer_t input_message_buffer, int *conf_state, gss_buffer_t output_message_buffer, int toktype); OM_uint32 kg_unseal (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); OM_uint32 kg_seal_size (OM_uint32 *minor_status, gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, OM_uint32 output_size, OM_uint32 *input_size); krb5_error_code kg_ctx_size (krb5_context kcontext, krb5_pointer arg, size_t *sizep); krb5_error_code kg_ctx_externalize (krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain); krb5_error_code kg_ctx_internalize (krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain); OM_uint32 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status); OM_uint32 kg_caller_provided_ccache_name (OM_uint32 *minor_status, int *out_caller_provided_name); OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status, const char **out_name); OM_uint32 kg_set_ccache_name (OM_uint32 *minor_status, const char *name); /** declarations of internal name mechanism functions **/ OM_uint32 krb5_gss_acquire_cred (OM_uint32*, /* minor_status */ gss_name_t, /* desired_name */ OM_uint32, /* time_req */ gss_OID_set, /* desired_mechs */ gss_cred_usage_t, /* cred_usage */ gss_cred_id_t*, /* output_cred_handle */ gss_OID_set*, /* actual_mechs */ OM_uint32* /* time_rec */ ); OM_uint32 krb5_gss_release_cred (OM_uint32*, /* minor_status */ gss_cred_id_t* /* cred_handle */ ); OM_uint32 krb5_gss_init_sec_context (OM_uint32*, /* minor_status */ gss_cred_id_t, /* claimant_cred_handle */ gss_ctx_id_t*, /* context_handle */ gss_name_t, /* target_name */ gss_OID, /* mech_type */ OM_uint32, /* req_flags */ OM_uint32, /* time_req */ gss_channel_bindings_t, /* input_chan_bindings */ gss_buffer_t, /* input_token */ gss_OID*, /* actual_mech_type */ gss_buffer_t, /* output_token */ OM_uint32*, /* ret_flags */ OM_uint32* /* time_rec */ ); OM_uint32 krb5_gss_accept_sec_context (OM_uint32*, /* minor_status */ gss_ctx_id_t*, /* context_handle */ gss_cred_id_t, /* verifier_cred_handle */ gss_buffer_t, /* input_token_buffer */ gss_channel_bindings_t, /* input_chan_bindings */ gss_name_t*, /* src_name */ gss_OID*, /* mech_type */ gss_buffer_t, /* output_token */ OM_uint32*, /* ret_flags */ OM_uint32*, /* time_rec */ gss_cred_id_t* /* delegated_cred_handle */ ); OM_uint32 krb5_gss_process_context_token (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t /* token_buffer */ ); OM_uint32 krb5_gss_delete_sec_context (OM_uint32*, /* minor_status */ gss_ctx_id_t*, /* context_handle */ gss_buffer_t /* output_token */ #ifdef _KERNEL /* */, OM_uint32 /* context verifier */ #endif ); OM_uint32 krb5_gss_context_time (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ OM_uint32* /* time_rec */ ); OM_uint32 krb5_gss_sign (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ #ifdef _KERNEL /* */, OM_uint32 /* context verifier */ #endif ); OM_uint32 krb5_gss_verify (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* token_buffer */ int* /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 /* context verifier */ #endif ); OM_uint32 krb5_gss_seal (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ int, /* qop_req */ gss_buffer_t, /* input_message_buffer */ int*, /* conf_state */ gss_buffer_t /* output_message_buffer */ #ifdef _KERNEL /* */, OM_uint32 /* context verifier */ #endif ); OM_uint32 krb5_gss_unseal (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int*, /* conf_state */ int* /* qop_state */ #ifdef _KERNEL /* */, OM_uint32 /* context verifier */ #endif ); OM_uint32 krb5_gss_display_status (OM_uint32*, /* minor_status */ OM_uint32, /* status_value */ int, /* status_type */ gss_OID, /* mech_type */ OM_uint32*, /* message_context */ gss_buffer_t /* status_string */ ); OM_uint32 krb5_gss_indicate_mechs (OM_uint32*, /* minor_status */ gss_OID_set* /* mech_set */ ); OM_uint32 krb5_gss_compare_name (OM_uint32*, /* minor_status */ gss_name_t, /* name1 */ gss_name_t, /* name2 */ int* /* name_equal */ ); OM_uint32 krb5_gss_display_name (OM_uint32*, /* minor_status */ gss_name_t, /* input_name */ gss_buffer_t, /* output_name_buffer */ gss_OID* /* output_name_type */ ); OM_uint32 krb5_gss_import_name (OM_uint32*, /* minor_status */ gss_buffer_t, /* input_name_buffer */ gss_OID, /* input_name_type */ gss_name_t* /* output_name */ ); OM_uint32 krb5_gss_release_name (OM_uint32*, /* minor_status */ gss_name_t* /* input_name */ ); OM_uint32 krb5_gss_inquire_cred (OM_uint32 *, /* minor_status */ gss_cred_id_t, /* cred_handle */ gss_name_t *, /* name */ OM_uint32 *, /* lifetime */ gss_cred_usage_t*,/* cred_usage */ gss_OID_set * /* mechanisms */ ); OM_uint32 krb5_gss_inquire_context (OM_uint32*, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_name_t*, /* initiator_name */ gss_name_t*, /* acceptor_name */ OM_uint32*, /* lifetime_rec */ gss_OID*, /* mech_type */ OM_uint32*, /* ret_flags */ int*, /* locally_initiated */ int* /* open */ ); /* New V2 entry points */ OM_uint32 krb5_gss_get_mic (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_qop_t, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t /* message_token */ ); OM_uint32 krb5_gss_verify_mic (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* message_token */ gss_qop_t * /* qop_state */ ); OM_uint32 krb5_gss_wrap (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t /* output_message_buffer */ ); OM_uint32 krb5_gss_unwrap (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ gss_qop_t * /* qop_state */ ); OM_uint32 krb5_gss_wrap_size_limit (OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ gss_qop_t, /* qop_req */ OM_uint32, /* req_output_size */ OM_uint32 * /* max_input_size */ ); OM_uint32 krb5_gss_import_name_object (OM_uint32 *, /* minor_status */ void *, /* input_name */ gss_OID, /* input_name_type */ gss_name_t * /* output_name */ ); OM_uint32 krb5_gss_export_name_object (OM_uint32 *, /* minor_status */ gss_name_t, /* input_name */ gss_OID, /* desired_name_type */ void * * /* output_name */ ); OM_uint32 krb5_gss_add_cred (OM_uint32 *, /* minor_status */ gss_cred_id_t, /* input_cred_handle */ gss_name_t, /* desired_name */ gss_OID, /* desired_mech */ gss_cred_usage_t, /* cred_usage */ OM_uint32, /* initiator_time_req */ OM_uint32, /* acceptor_time_req */ gss_cred_id_t *, /* output_cred_handle */ gss_OID_set *, /* actual_mechs */ OM_uint32 *, /* initiator_time_rec */ OM_uint32 * /* acceptor_time_rec */ ); OM_uint32 krb5_gss_inquire_cred_by_mech (OM_uint32 *, /* minor_status */ gss_cred_id_t, /* cred_handle */ gss_OID, /* mech_type */ gss_name_t *, /* name */ OM_uint32 *, /* initiator_lifetime */ OM_uint32 *, /* acceptor_lifetime */ gss_cred_usage_t * /* cred_usage */ ); OM_uint32 krb5_gss_export_sec_context (OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t /* interprocess_token */ ); OM_uint32 krb5_gss_import_sec_context (OM_uint32 *, /* minor_status */ gss_buffer_t, /* interprocess_token */ gss_ctx_id_t * /* context_handle */ /* Note no _KERNEL context verifier */ ); krb5_error_code krb5_gss_ser_init(krb5_context); OM_uint32 krb5_gss_release_oid (OM_uint32 *, /* minor_status */ gss_OID * /* oid */ ); OM_uint32 krb5_gss_internal_release_oid (OM_uint32 *, /* minor_status */ gss_OID * /* oid */ ); OM_uint32 krb5_gss_inquire_names_for_mech (OM_uint32 *, /* minor_status */ gss_OID, /* mechanism */ gss_OID_set * /* name_types */ ); /* SUNW15resync - XXX nullify? */ OM_uint32 krb5_gss_canonicalize_name (OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ const gss_OID, /* mech_type */ gss_name_t * /* output_name */ ); OM_uint32 krb5_gss_export_name (OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_buffer_t /* exported_name */ ); OM_uint32 krb5_gss_duplicate_name (OM_uint32 *, /* minor_status */ const gss_name_t, /* input_name */ gss_name_t * /* dest_name */ ); OM_uint32 krb5_gss_validate_cred (OM_uint32 *, /* minor_status */ gss_cred_id_t /* cred */ ); OM_uint32 krb5_gss_validate_cred_1(OM_uint32 * /* minor_status */, gss_cred_id_t /* cred_handle */, krb5_context /* context */); gss_OID krb5_gss_convert_static_mech_oid(gss_OID oid); krb5_error_code gss_krb5int_make_seal_token_v3(krb5_context, krb5_gss_ctx_id_rec *, const gss_buffer_desc *, gss_buffer_t, int, int); OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr, 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); /* * SUNW15resync * Solaris specific interfaces start */ OM_uint32 krb5_gss_store_cred ( OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* input_cred */ gss_cred_usage_t, /* cred_usage */ const gss_OID, /* desired_mech */ OM_uint32, /* overwrite_cred */ OM_uint32, /* default_cred */ gss_OID_set *, /* elements_stored */ gss_cred_usage_t * /* cred_usage_stored */ ); OM_uint32 krb5_pname_to_uid( OM_uint32 *, /* minor status */ const gss_name_t, /* pname */ uid_t * /* uidOUt */ ); OM_uint32 krb5_gss_userok( OM_uint32 *, /* minor status */ const gss_name_t, /* remote user principal name */ const char *, /* local unix user name */ int * /* remote user ok to login w/out pw? */ ); /* * SUNW15resync * Solaris specific interfaces end */ /* * These take unglued krb5-mech-specific contexts. */ #define GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH 11 #define GSS_KRB5_GET_TKT_FLAGS_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x01" #ifndef _KERNEL OM_uint32 gss_krb5int_get_tkt_flags (OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t *data_set); OM_uint32 KRB5_CALLCONV gss_krb5int_copy_ccache (OM_uint32 *minor_status, gss_cred_id_t cred_handle, krb5_ccache out_ccache); #define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH 11 #define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x04" struct krb5_gss_set_allowable_enctypes_req { OM_uint32 num_ktypes; krb5_enctype *ktypes; }; #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" OM_uint32 gss_krb5int_inq_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); OM_uint32 KRB5_CALLCONV gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, gss_cred_id_t cred, OM_uint32 num_ktypes, krb5_enctype *ktypes); #endif /* _KERNEL */ #if 0 /* * SUNW17PACresync * These two functions not needed yet, revisit for full 1.7 resync. */ OM_uint32 KRB5_CALLCONV gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, gss_cred_id_t cred, const gss_OID desired_oid, const gss_buffer_t value); OM_uint32 KRB5_CALLCONV gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, OM_uint32 version, void **kctx); #endif #ifndef _KERNEL #define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH 11 #define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06" OM_uint32 gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t *data_set); #define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH 11 #define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07" OM_uint32 gss_krb5int_free_lucid_sec_context(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); extern k5_mutex_t kg_kdc_flag_mutex; krb5_error_code krb5_gss_init_context (krb5_context *ctxp); #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" OM_uint32 gss_krb5int_inq_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); #define GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH 11 #define GSS_KRB5_USE_KDC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x08" OM_uint32 krb5int_gss_use_kdc_context(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); krb5_error_code krb5_gss_use_kdc_context(void); #define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH 11 #define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x09" OM_uint32 gss_krb5int_register_acceptor_identity(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); #define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH 11 #define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" OM_uint32 gss_krb5int_extract_authz_data_from_sec_context(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t *ad_data); #define GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH 11 #define GSS_KRB5_SET_CRED_RCACHE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0b" OM_uint32 gss_krb5int_set_cred_rcache(OM_uint32 *, gss_cred_id_t, const gss_OID, const gss_buffer_t); #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 11 #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c" OM_uint32 gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); #endif /* _KERNEL */ OM_uint32 gss_krb5int_initialize_library(void); void gss_krb5int_cleanup_library(void); /* For error message handling. */ /* Returns a shared string, not a private copy! */ extern char * krb5_gss_get_error_message(OM_uint32 minor_code); extern void krb5_gss_save_error_string(OM_uint32 minor_code, char *msg); extern void krb5_gss_save_error_message(OM_uint32 minor_code, const char *format, ...) #if !defined(__cplusplus) && (__GNUC__ > 2) __attribute__((__format__(__printf__, 2, 3))) #endif ; extern void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx); #define get_error_message krb5_gss_get_error_message #define save_error_string krb5_gss_save_error_string #define save_error_message krb5_gss_save_error_message /* Solaris Kerberos */ #ifdef _KERNEL #define save_error_info(m, ctx) #else #define save_error_info krb5_gss_save_error_info #endif extern void krb5_gss_delete_error_info(void *p); /* Prefix concatenated with Kerberos encryption type */ #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04" #endif /* _GSSAPIP_KRB5_H_ */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef __GSSAPI_ERR_KRB5_H #define __GSSAPI_ERR_KRB5_H /* * gssapi_err_krb5.h: * This file is automatically generated; please do not edit it. */ #define KG_CCACHE_NOMATCH (39756032L) #define KG_KEYTAB_NOMATCH (39756033L) #define KG_TGT_MISSING (39756034L) #define KG_NO_SUBKEY (39756035L) #define KG_CONTEXT_ESTABLISHED (39756036L) #define KG_BAD_SIGN_TYPE (39756037L) #define KG_BAD_LENGTH (39756038L) #define KG_CTX_INCOMPLETE (39756039L) #define KG_CONTEXT (39756040L) #define KG_CRED (39756041L) #define KG_ENC_DESC (39756042L) #define KG_BAD_SEQ (39756043L) #define KG_EMPTY_CCACHE (39756044L) #define KG_NO_CTYPES (39756045L) #define KG_LUCID_VERSION (39756046L) #define ERROR_TABLE_BASE_k5g (39756032L) /* for compatibility with older versions... */ #define k5g_err_base ERROR_TABLE_BASE_k5g #endif /* ! __GSSAPI_ERR_KRB5_H */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GSSAPI_GENERIC_H_ #define _GSSAPI_GENERIC_H_ /* * $Id: gssapi_generic.h 15252 2003-03-06 20:26:39Z lxs $ */ #include #if defined(__cplusplus) && !defined(GSSAPIGENERIC_BEGIN_DECLS) #define GSSAPIGENERIC_BEGIN_DECLS extern "C" { #define GSSAPIGENERIC_END_DECLS } #else #define GSSAPIGENERIC_BEGIN_DECLS #define GSSAPIGENERIC_END_DECLS #endif GSSAPIGENERIC_BEGIN_DECLS /* SUNW14resync */ #ifndef GSS_DLLIMP #define GSS_DLLIMP #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; extern gss_OID gss_nt_service_name_v2; GSS_DLLIMP extern gss_OID gss_nt_service_name; extern gss_OID gss_nt_exported_name; GSSAPIGENERIC_END_DECLS #endif /* _GSSAPI_GENERIC_H_ */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifndef _GSSAPI_KRB5_H_ #define _GSSAPI_KRB5_H_ #include #include #include /* SUNW15resync */ #ifndef GSS_DLLIMP #define GSS_DLLIMP #endif /* C++ friendlyness */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* 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". */ GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5; GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5_old; GSS_DLLIMP extern const gss_OID_desc * const gss_mech_krb5_wrong; GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5; GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5_old; GSS_DLLIMP extern const gss_OID_set_desc * const gss_mech_set_krb5_both; GSS_DLLIMP extern const gss_OID_desc * const gss_nt_krb5_name; GSS_DLLIMP extern const gss_OID_desc * const gss_nt_krb5_principal; GSS_DLLIMP extern const gss_OID_desc krb5_gss_oid_array[]; #define gss_krb5_nt_general_name gss_nt_krb5_name #define gss_krb5_nt_principal gss_nt_krb5_principal #define gss_krb5_nt_service_name gss_nt_service_name #define gss_krb5_nt_user_name gss_nt_user_name #define gss_krb5_nt_machine_uid_name gss_nt_machine_uid_name #define gss_krb5_nt_string_uid_name gss_nt_string_uid_name #if defined(_WIN32) typedef unsigned __int64 gss_uint64; #else /*windows*/ #ifdef _KERNEL #include #else /* _KERNEL */ #include #endif /* _KERNEL */ typedef uint64_t gss_uint64; #endif typedef struct gss_krb5_lucid_key { OM_uint32 type; /* key encryption type */ OM_uint32 length; /* length of key data */ void * data; /* actual key data */ } gss_krb5_lucid_key_t; typedef struct gss_krb5_rfc1964_keydata { OM_uint32 sign_alg; /* signing algorthm */ OM_uint32 seal_alg; /* seal/encrypt algorthm */ gss_krb5_lucid_key_t ctx_key; /* Context key (Kerberos session key or subkey) */ } gss_krb5_rfc1964_keydata_t; typedef struct gss_krb5_cfx_keydata { OM_uint32 have_acceptor_subkey; /* 1 if there is an acceptor_subkey present, 0 otherwise */ gss_krb5_lucid_key_t ctx_key; /* Context key (Kerberos session key or subkey) */ gss_krb5_lucid_key_t acceptor_subkey; /* acceptor-asserted subkey or 0's if no acceptor subkey */ } gss_krb5_cfx_keydata_t; typedef struct gss_krb5_lucid_context_v1 { OM_uint32 version; /* Structure version number (1) MUST be at beginning of struct! */ OM_uint32 initiate; /* Are we the initiator? */ OM_uint32 endtime; /* expiration time of context */ gss_uint64 send_seq; /* sender sequence number */ gss_uint64 recv_seq; /* receive sequence number */ OM_uint32 protocol; /* 0: rfc1964, 1: draft-ietf-krb-wg-gssapi-cfx-07 */ /* * if (protocol == 0) rfc1964_kd should be used * and cfx_kd contents are invalid and should be zero * if (protocol == 1) cfx_kd should be used * and rfc1964_kd contents are invalid and should be zero */ gss_krb5_rfc1964_keydata_t rfc1964_kd; gss_krb5_cfx_keydata_t cfx_kd; } gss_krb5_lucid_context_v1_t; /* * Mask for determining the returned structure version. * See example below for usage. */ typedef struct gss_krb5_lucid_context_version { OM_uint32 version; /* Structure version number */ } gss_krb5_lucid_context_version_t; /* Alias for Heimdal compat. */ #define gsskrb5_register_acceptor_identity krb5_gss_register_acceptor_identity OM_uint32 KRB5_CALLCONV krb5_gss_register_acceptor_identity(const char *); OM_uint32 KRB5_CALLCONV gss_krb5_copy_ccache (OM_uint32 *minor_status, gss_cred_id_t cred_handle, krb5_ccache out_ccache); OM_uint32 KRB5_CALLCONV gss_krb5_ccache_name (OM_uint32 *minor_status, const char *name, const char **out_name); /* * gss_krb5_set_allowable_enctypes * * This function may be called by a context initiator after calling * gss_acquire_cred(), but before calling gss_init_sec_context(), * to restrict the set of enctypes which will be negotiated during * context establishment to those in the provided array. * * 'cred' must be a valid credential handle obtained via * gss_acquire_cred(). It may not be GSS_C_NO_CREDENTIAL. * gss_acquire_cred() may have been called to get a handle to * the default credential. * * The purpose of this function is to limit the keys that may * be exported via gss_krb5_export_lucid_sec_context(); thus it * should limit the enctypes of all keys that will be needed * after the security context has been established. * (i.e. context establishment may use a session key with a * stronger enctype than in the provided array, however a * subkey must be established within the enctype limits * established by this function.) * */ OM_uint32 KRB5_CALLCONV gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, gss_cred_id_t cred, OM_uint32 num_ktypes, krb5_enctype *ktypes); /* * Returns a non-opaque (lucid) version of the internal context * information. * * Note that context_handle must not be used again by the caller * after this call. The GSS implementation is free to release any * resources associated with the original context. It is up to the * GSS implementation whether it returns pointers to existing data, * or copies of the data. The caller should treat the returned * lucid context as read-only. * * The caller must call gss_krb5_free_lucid_context() to free * the context and allocated resources when it is finished with it. * * 'version' is an integer indicating the highest version of lucid * context understood by the caller. The highest version * understood by both the caller and the GSS implementation must * be returned. The caller can determine which version of the * structure was actually returned by examining the version field * of the returned structure. gss_krb5_lucid_context_version_t * may be used as a mask to examine the returned structure version. * * If there are no common versions, an error should be returned. * (XXX Need error definition(s)) * * For example: * void *return_ctx; * gss_krb5_lucid_context_v1_t *ctx; * OM_uint32 min_stat, maj_stat; * OM_uint32 vers; * gss_ctx_id_t *ctx_handle; * * maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, * ctx_handle, 1, &return_ctx); * // Verify success * * vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version; * switch (vers) { * case 1: * ctx = (gss_krb5_lucid_context_v1_t *) return_ctx; * break; * default: * // Error, unknown version returned * break; * } * */ OM_uint32 KRB5_CALLCONV gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, OM_uint32 version, void **kctx); /* * Frees the allocated storage associated with an * exported struct gss_krb5_lucid_context. */ OM_uint32 KRB5_CALLCONV gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *kctx); OM_uint32 KRB5_CALLCONV gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, const gss_ctx_id_t context_handle, int ad_type, gss_buffer_t ad_data); OM_uint32 KRB5_CALLCONV gss_krb5_set_cred_rcache(OM_uint32 *minor_status, gss_cred_id_t cred, krb5_rcache rcache); OM_uint32 KRB5_CALLCONV gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, krb5_timestamp *); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _GSSAPI_KRB5_H_ */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" extern const struct krb5_hash_provider krb5int_hash_crc32; extern const struct krb5_hash_provider krb5int_hash_md5; extern const struct krb5_hash_provider krb5int_hash_sha1; /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2009 by the Massachusetts Institute of Technology, * Cambridge, MA, USA. All Rights Reserved. * * This software is being provided to you, the LICENSEE, by the * Massachusetts Institute of Technology (M.I.T.) under the following * license. By obtaining, using and/or copying this software, you agree * that you have read, understood, and will comply with these terms and * conditions: * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute * this software and its documentation for any purpose and without fee or * royalty is hereby granted, provided that you agree to comply with the * following copyright notice and statements, including the disclaimer, and * that the same appear on ALL copies of the software and documentation, * including modifications that you make for internal use or for * distribution: * * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. * * The name of the Massachusetts Institute of Technology or M.I.T. may NOT * be used in advertising or publicity pertaining to distribution of the * software. Title to copyright in this software and any associated * documentation shall at all times remain with M.I.T., and USER agrees to * preserve same. * * Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* * This prototype for k5-int.h (Krb5 internals include file) * includes the user-visible definitions from krb5.h and then * includes other definitions that are not user-visible but are * required for compiling Kerberos internal routines. * * John Gilmore, Cygnus Support, Sat Jan 21 22:45:52 PST 1995 */ #ifndef _KRB5_INT_H #define _KRB5_INT_H #ifdef KRB5_GENERAL__ #error krb5.h included before k5-int.h #endif /* KRB5_GENERAL__ */ #ifndef _KERNEL #include #include #else #include #include #endif #ifdef DEBUG #if !defined(KRB5_DEBUG) #define KRB5_DEBUG #endif #ifndef KRB5_LOG_LVL #define KRB5_LOG_LVL KRB5_ERR #endif #endif /* DEBUG */ #ifdef _KERNEL #ifdef DEBUG #include #include extern void prom_printf(); #endif /* DEBUG */ #else /* !_KERNEL */ #define prom_printf printf #endif /* !_KERNEL */ #ifdef KRB5_LOG_LVL /* krb5_log is used to set the logging level to determine what class of messages * are output by the mech. Note, more than one logging level can be used by * bit or'ing the log values together. * * All log messages are captured by syslog. */ extern unsigned int krb5_log; /* Note, these defines should be mutually exclusive bit fields */ #define KRB5_ERR 1 /* Use this debug log level for error path logging. */ #define KRB5_INFO 2 /* Use this debug log level for informational messages. */ #ifdef _KERNEL #define KRB5_LOG1(A, B, C, D) \ ((void)((krb5_log) && (krb5_log & (A)) && (printf((B), (C), (D)), TRUE))) #define KRB5_LOG(A, B, C) \ ((void)((krb5_log) && (krb5_log & (A)) && (printf((B), (C)), TRUE))) #define KRB5_LOG0(A, B) \ ((void)((krb5_log) && (krb5_log & (A)) && (printf((B)), TRUE))) #else /* !_KERNEL */ #include #define KRB5_LOG1(A, B, C, D) \ ((void)((krb5_log) && (krb5_log & (A)) && \ (syslog(LOG_DEBUG, (B), (C), (D)), TRUE))) #define KRB5_LOG(A, B, C) \ ((void)((krb5_log) && (krb5_log & (A)) && \ (syslog(LOG_DEBUG, (B), (C)), TRUE))) #define KRB5_LOG0(A, B) \ ((void)((krb5_log) && (krb5_log & (A)) && \ (syslog(LOG_DEBUG, B), TRUE))) #endif /* _KERNEL */ #else /* ! KRB5_LOG_LVL */ #define KRB5_LOG1(A, B, C, D) #define KRB5_LOG(A, B, C) #define KRB5_LOG0(A, B) #endif /* KRB5_LOG_LVL */ #ifdef POSIX_TYPES #define timetype time_t #else #define timetype long #endif /* * Begin "k5-config.h" */ #ifndef KRB5_CONFIG__ #define KRB5_CONFIG__ /* * Machine-type definitions: PC Clone 386 running Microloss Windows */ #if defined(_MSDOS) || defined(_WIN32) #include "win-mac.h" /* Kerberos Windows initialization file */ #define KERBEROS_INI "kerberos.ini" #define INI_FILES "Files" #define INI_KRB_CCACHE "krb5cc" /* Location of the ccache */ #define INI_KRB5_CONF "krb5.ini" /* Location of krb5.conf file */ #define ANSI_STDIO #endif #ifndef _KERNEL #ifndef KRB5_AUTOCONF__ #define KRB5_AUTOCONF__ #include "autoconf.h" #endif #endif /* !_KERNEL */ #ifndef KRB5_SYSTYPES__ #define KRB5_SYSTYPES__ #ifndef _KERNEL #ifdef HAVE_SYS_TYPES_H /* From autoconf.h */ #include #else /* HAVE_SYS_TYPES_H */ typedef unsigned long u_long; typedef unsigned int u_int; typedef unsigned short u_short; typedef unsigned char u_char; #endif /* HAVE_SYS_TYPES_H */ #endif /* KRB5_SYSTYPES__ */ #endif /* !_KERNEL */ /* #include "k5-platform.h" SUNW XXX */ /* not used in krb5.h (yet) */ typedef uint64_t krb5_ui_8; typedef int64_t krb5_int64; #define DEFAULT_PWD_STRING1 "Enter password:" #define DEFAULT_PWD_STRING2 "Re-enter password for verification:" #define KRB5_KDB_MAX_LIFE (60*60*24) /* one day */ #define KRB5_KDB_MAX_RLIFE (60*60*24*365) /* one year */ #define KRB5_KDB_EXPIRATION 2145830400 /* Thu Jan 1 00:00:00 2038 UTC */ #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ #define KRB5_DEFAULT_RENEW_LIFE 7*24*60*60 /* 7 Days */ /* * Windows requires a different api interface to each function. Here * just define it as NULL. */ #ifndef KRB5_CALLCONV #define KRB5_CALLCONV #define KRB5_CALLCONV_C #endif #ifndef O_BINARY #define O_BINARY 0 #endif #endif /* KRB5_CONFIG__ */ /* * End "k5-config.h" */ /* * After loading the configuration definitions, load the Kerberos definitions. */ #ifndef _KERNEL #include #include "profile.h" #endif #include #ifndef _KERNEL #if 1 /* def NEED_SOCKETS */ #include #include #else #ifndef SOCK_DGRAM struct sockaddr; #endif #endif #endif /* Get mutex support; currently used only for the replay cache. */ #include "k5-thread.h" /* krb5/krb5.h includes many other .h files in the krb5 subdirectory. The ones that it doesn't include, we include below. */ /* * Begin "k5-errors.h" */ #ifndef KRB5_ERRORS__ #define KRB5_ERRORS__ /* Error codes used in KRB_ERROR protocol messages. Return values of library routines are based on a different error table (which allows non-ambiguous error codes between subsystems) */ /* KDC errors */ #define KDC_ERR_NONE 0 /* No error */ #define KDC_ERR_NAME_EXP 1 /* Client's entry in DB expired */ #define KDC_ERR_SERVICE_EXP 2 /* Server's entry in DB expired */ #define KDC_ERR_BAD_PVNO 3 /* Requested pvno not supported */ #define KDC_ERR_C_OLD_MAST_KVNO 4 /* C's key encrypted in old master */ #define KDC_ERR_S_OLD_MAST_KVNO 5 /* S's key encrypted in old master */ #define KDC_ERR_C_PRINCIPAL_UNKNOWN 6 /* Client not found in Kerberos DB */ #define KDC_ERR_S_PRINCIPAL_UNKNOWN 7 /* Server not found in Kerberos DB */ #define KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 /* Multiple entries in Kerberos DB */ #define KDC_ERR_NULL_KEY 9 /* The C or S has a null key */ #define KDC_ERR_CANNOT_POSTDATE 10 /* Tkt ineligible for postdating */ #define KDC_ERR_NEVER_VALID 11 /* Requested starttime > endtime */ #define KDC_ERR_POLICY 12 /* KDC policy rejects request */ #define KDC_ERR_BADOPTION 13 /* KDC can't do requested opt. */ #define KDC_ERR_ENCTYPE_NOSUPP 14 /* No support for encryption type */ #define KDC_ERR_SUMTYPE_NOSUPP 15 /* No support for checksum type */ #define KDC_ERR_PADATA_TYPE_NOSUPP 16 /* No support for padata type */ #define KDC_ERR_TRTYPE_NOSUPP 17 /* No support for transited type */ #define KDC_ERR_CLIENT_REVOKED 18 /* C's creds have been revoked */ #define KDC_ERR_SERVICE_REVOKED 19 /* S's creds have been revoked */ #define KDC_ERR_TGT_REVOKED 20 /* TGT has been revoked */ #define KDC_ERR_CLIENT_NOTYET 21 /* C not yet valid */ #define KDC_ERR_SERVICE_NOTYET 22 /* S not yet valid */ #define KDC_ERR_KEY_EXP 23 /* Password has expired */ #define KDC_ERR_PREAUTH_FAILED 24 /* Preauthentication failed */ #define KDC_ERR_PREAUTH_REQUIRED 25 /* Additional preauthentication */ /* required */ #define KDC_ERR_SERVER_NOMATCH 26 /* Requested server and */ /* ticket don't match*/ #define KDC_ERR_MUST_USE_USER2USER 27 /* Server principal valid for */ /* user2user only */ #define KDC_ERR_PATH_NOT_ACCEPTED 28 /* KDC policy rejected transited */ /* path */ #define KDC_ERR_SVC_UNAVAILABLE 29 /* A service is not * available that is * required to process the * request */ /* Application errors */ #define KRB_AP_ERR_BAD_INTEGRITY 31 /* Decrypt integrity check failed */ #define KRB_AP_ERR_TKT_EXPIRED 32 /* Ticket expired */ #define KRB_AP_ERR_TKT_NYV 33 /* Ticket not yet valid */ #define KRB_AP_ERR_REPEAT 34 /* Request is a replay */ #define KRB_AP_ERR_NOT_US 35 /* The ticket isn't for us */ #define KRB_AP_ERR_BADMATCH 36 /* Ticket/authenticator don't match */ #define KRB_AP_ERR_SKEW 37 /* Clock skew too great */ #define KRB_AP_ERR_BADADDR 38 /* Incorrect net address */ #define KRB_AP_ERR_BADVERSION 39 /* Protocol version mismatch */ #define KRB_AP_ERR_MSG_TYPE 40 /* Invalid message type */ #define KRB_AP_ERR_MODIFIED 41 /* Message stream modified */ #define KRB_AP_ERR_BADORDER 42 /* Message out of order */ #define KRB_AP_ERR_BADKEYVER 44 /* Key version is not available */ #define KRB_AP_ERR_NOKEY 45 /* Service key not available */ #define KRB_AP_ERR_MUT_FAIL 46 /* Mutual authentication failed */ #define KRB_AP_ERR_BADDIRECTION 47 /* Incorrect message direction */ #define KRB_AP_ERR_METHOD 48 /* Alternative authentication */ /* method required */ #define KRB_AP_ERR_BADSEQ 49 /* Incorrect sequence numnber */ /* in message */ #define KRB_AP_ERR_INAPP_CKSUM 50 /* Inappropriate type of */ /* checksum in message */ #define KRB_AP_PATH_NOT_ACCEPTED 51 /* Policy rejects transited path */ #define KRB_ERR_RESPONSE_TOO_BIG 52 /* Response too big for UDP, */ /* retry with TCP */ /* other errors */ #define KRB_ERR_GENERIC 60 /* Generic error (description */ /* in e-text) */ #define KRB_ERR_FIELD_TOOLONG 61 /* Field is too long for impl. */ /* PKINIT server-reported errors */ #define KDC_ERR_CLIENT_NOT_TRUSTED 62 /* client cert not trusted */ #define KDC_ERR_INVALID_SIG 64 /* client signature verify failed */ #define KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED 65 /* invalid Diffie-Hellman parameters */ #define KDC_ERR_CERTIFICATE_MISMATCH 66 #define KRB_AP_ERR_NO_TGT 67 #define KDC_ERR_WRONG_REALM 68 #define KRB_AP_ERR_USER_TO_USER_REQUIRED 69 #define KDC_ERR_CANT_VERIFY_CERTIFICATE 70 /* client cert not verifiable to */ /* trusted root cert */ #define KDC_ERR_INVALID_CERTIFICATE 71 /* client cert had invalid signature */ #define KDC_ERR_REVOKED_CERTIFICATE 72 /* client cert was revoked */ #define KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 /* client cert revoked, reason unknown */ #define KDC_ERR_CLIENT_NAME_MISMATCH 75 /* mismatch between client cert and */ /* principal name */ #define KDC_ERR_INCONSISTENT_KEY_PURPOSE 77 /* bad extended key use */ #define KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED 78 /* bad digest algorithm in client cert */ #define KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED 79 /* missing paChecksum in PA-PK-AS-REQ */ #define KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED 80 /* bad digest algorithm in SignedData */ #define KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED 81 #endif /* KRB5_ERRORS__ */ /* * End "k5-errors.h" */ /* * This structure is returned in the e-data field of the KRB-ERROR * message when the error calling for an alternative form of * authentication is returned, KRB_AP_METHOD. */ typedef struct _krb5_alt_method { krb5_magic magic; krb5_int32 method; unsigned int length; krb5_octet *data; } krb5_alt_method; /* * A null-terminated array of this structure is returned by the KDC as * the data part of the ETYPE_INFO preauth type. It informs the * client which encryption types are supported. * The same data structure is used by both etype-info and etype-info2 * but s2kparams must be null when encoding etype-info. */ typedef struct _krb5_etype_info_entry { krb5_magic magic; krb5_enctype etype; unsigned int length; krb5_octet *salt; krb5_data s2kparams; } krb5_etype_info_entry; /* * This is essentially -1 without sign extension which can screw up * comparisons on 64 bit machines. If the length is this value, then * the salt data is not present. This is to distinguish between not * being set and being of 0 length. */ #define KRB5_ETYPE_NO_SALT VALID_UINT_BITS typedef krb5_etype_info_entry ** krb5_etype_info; /* RFC 4537 */ typedef struct _krb5_etype_list { int length; krb5_enctype *etypes; } krb5_etype_list; /* * a sam_challenge is returned for alternate preauth */ /* SAMFlags ::= BIT STRING { use-sad-as-key[0], send-encrypted-sad[1], must-pk-encrypt-sad[2] } */ /* PA-SAM-CHALLENGE ::= SEQUENCE { sam-type[0] INTEGER, sam-flags[1] SAMFlags, sam-type-name[2] GeneralString OPTIONAL, sam-track-id[3] GeneralString OPTIONAL, sam-challenge-label[4] GeneralString OPTIONAL, sam-challenge[5] GeneralString OPTIONAL, sam-response-prompt[6] GeneralString OPTIONAL, sam-pk-for-sad[7] EncryptionKey OPTIONAL, sam-nonce[8] INTEGER OPTIONAL, sam-cksum[9] Checksum OPTIONAL } */ /* sam_type values -- informational only */ #define PA_SAM_TYPE_ENIGMA 1 /* Enigma Logic */ #define PA_SAM_TYPE_DIGI_PATH 2 /* Digital Pathways */ #define PA_SAM_TYPE_SKEY_K0 3 /* S/key where KDC has key 0 */ #define PA_SAM_TYPE_SKEY 4 /* Traditional S/Key */ #define PA_SAM_TYPE_SECURID 5 /* Security Dynamics */ #define PA_SAM_TYPE_CRYPTOCARD 6 /* CRYPTOCard */ #if 1 /* XXX need to figure out who has which numbers assigned */ #define PA_SAM_TYPE_ACTIVCARD_DEC 6 /* ActivCard decimal mode */ #define PA_SAM_TYPE_ACTIVCARD_HEX 7 /* ActivCard hex mode */ #define PA_SAM_TYPE_DIGI_PATH_HEX 8 /* Digital Pathways hex mode */ #endif #define PA_SAM_TYPE_EXP_BASE 128 /* experimental */ #define PA_SAM_TYPE_GRAIL (PA_SAM_TYPE_EXP_BASE+0) /* testing */ #define PA_SAM_TYPE_SECURID_PREDICT (PA_SAM_TYPE_EXP_BASE+1) /* special */ typedef struct _krb5_predicted_sam_response { krb5_magic magic; krb5_keyblock sam_key; krb5_flags sam_flags; /* Makes key munging easier */ krb5_timestamp stime; /* time on server, for replay detection */ krb5_int32 susec; krb5_principal client; krb5_data msd; /* mechanism specific data */ } krb5_predicted_sam_response; typedef struct _krb5_sam_challenge { krb5_magic magic; krb5_int32 sam_type; /* information */ krb5_flags sam_flags; /* KRB5_SAM_* values */ krb5_data sam_type_name; krb5_data sam_track_id; krb5_data sam_challenge_label; krb5_data sam_challenge; krb5_data sam_response_prompt; krb5_data sam_pk_for_sad; krb5_int32 sam_nonce; krb5_checksum sam_cksum; } krb5_sam_challenge; typedef struct _krb5_sam_key { /* reserved for future use */ krb5_magic magic; krb5_keyblock sam_key; } krb5_sam_key; typedef struct _krb5_enc_sam_response_enc { krb5_magic magic; krb5_int32 sam_nonce; krb5_timestamp sam_timestamp; krb5_int32 sam_usec; krb5_data sam_sad; } krb5_enc_sam_response_enc; typedef struct _krb5_sam_response { krb5_magic magic; krb5_int32 sam_type; /* informational */ krb5_flags sam_flags; /* KRB5_SAM_* values */ krb5_data sam_track_id; /* copied */ krb5_enc_data sam_enc_key; /* krb5_sam_key - future use */ krb5_enc_data sam_enc_nonce_or_ts; /* krb5_enc_sam_response_enc */ krb5_int32 sam_nonce; krb5_timestamp sam_patimestamp; } krb5_sam_response; typedef struct _krb5_sam_challenge_2 { krb5_data sam_challenge_2_body; krb5_checksum **sam_cksum; /* Array of checksums */ } krb5_sam_challenge_2; typedef struct _krb5_sam_challenge_2_body { krb5_magic magic; krb5_int32 sam_type; /* information */ krb5_flags sam_flags; /* KRB5_SAM_* values */ krb5_data sam_type_name; krb5_data sam_track_id; krb5_data sam_challenge_label; krb5_data sam_challenge; krb5_data sam_response_prompt; krb5_data sam_pk_for_sad; krb5_int32 sam_nonce; krb5_enctype sam_etype; } krb5_sam_challenge_2_body; typedef struct _krb5_sam_response_2 { krb5_magic magic; krb5_int32 sam_type; /* informational */ krb5_flags sam_flags; /* KRB5_SAM_* values */ krb5_data sam_track_id; /* copied */ krb5_enc_data sam_enc_nonce_or_sad; /* krb5_enc_sam_response_enc */ krb5_int32 sam_nonce; } krb5_sam_response_2; typedef struct _krb5_enc_sam_response_enc_2 { krb5_magic magic; krb5_int32 sam_nonce; krb5_data sam_sad; } krb5_enc_sam_response_enc_2; /* * Keep the pkinit definitions in a separate file so that the plugin * only has to include k5-int-pkinit.h rather than k5-int.h */ #include "k5-int-pkinit.h" /* * Begin "dbm.h" */ #ifndef _KERNEL /* * Since we are always using db, use the db-ndbm include header file. */ #include "db-ndbm.h" #endif /* !KERNEL */ /* * End "dbm.h" */ /* * Begin "ext-proto.h" */ #ifndef KRB5_EXT_PROTO__ #define KRB5_EXT_PROTO__ #ifndef _KERNEL #include #include #endif /* !_KERNEL */ #ifndef HAVE_STRDUP extern char *strdup (const char *); #endif #ifndef _KERNEL #ifdef HAVE_UNISTD_H #include #endif #endif /* !_KERNEL */ #endif /* KRB5_EXT_PROTO__ */ /* * End "ext-proto.h" */ /* * Begin "sysincl.h" */ #ifndef KRB5_SYSINCL__ #define KRB5_SYSINCL__ #ifndef KRB5_SYSTYPES__ #define KRB5_SYSTYPES__ /* needed for much of the rest -- but already handled in krb5.h? */ /* #include */ #endif /* KRB5_SYSTYPES__ */ #ifdef _KERNEL #include #else #ifdef HAVE_SYS_TIME_H #include #ifdef TIME_WITH_SYS_TIME #include #endif #else #include #endif #endif /* _KERNEL */ #ifdef HAVE_SYS_STAT_H #include /* struct stat, stat() */ #endif #ifdef HAVE_SYS_PARAM_H #include /* MAXPATHLEN */ #endif #ifdef HAVE_SYS_FILE_H #include /* prototypes for file-related syscalls; flags for open & friends */ #endif #ifdef _KERNEL #include #else #include #endif #endif /* KRB5_SYSINCL__ */ /* * End "sysincl.h" */ /* * Begin "los-proto.h" */ #ifndef KRB5_LIBOS_PROTO__ #define KRB5_LIBOS_PROTO__ #endif #ifndef _KERNEL #include struct addrlist; struct sendto_callback_info; #endif /* libos.spec */ krb5_error_code krb5_lock_file (krb5_context, int, int); krb5_error_code krb5_unlock_file (krb5_context, int); krb5_error_code krb5_sendto_kdc (krb5_context, const krb5_data *, const krb5_data *, krb5_data *, int *, int); /* Solaris Kerberos */ krb5_error_code krb5_sendto_kdc2 (krb5_context, const krb5_data *, const krb5_data *, krb5_data *, int *, int, char **); krb5_error_code krb5_get_krbhst (krb5_context, const krb5_data *, char *** ); krb5_error_code krb5_free_krbhst (krb5_context, char * const * ); krb5_error_code krb5_create_secure_file (krb5_context, const char * pathname); int krb5_net_read (krb5_context, int , char *, int); int krb5_net_write (krb5_context, int , const char *, int); krb5_error_code krb5_gen_replay_name (krb5_context, const krb5_address *, const char *, char **); #ifndef _KERNEL krb5_error_code krb5_sync_disk_file (krb5_context, FILE *fp); krb5_error_code krb5_open_pkcs11_session(CK_SESSION_HANDLE *); krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *); krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *); krb5_error_code krb5int_sendto (krb5_context context, const krb5_data *message, const struct addrlist *addrs, struct sendto_callback_info* callback_info, krb5_data *reply, struct sockaddr *localaddr, socklen_t *localaddrlen, struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *addr_used, int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data); krb5_error_code krb5int_get_fq_local_hostname (char *, size_t); krb5_error_code krb5_set_debugging_time (krb5_context, krb5_timestamp, krb5_int32); krb5_error_code krb5_use_natural_time (krb5_context); krb5_error_code krb5_set_time_offsets (krb5_context, krb5_timestamp, krb5_int32); krb5_error_code krb5int_check_clockskew(krb5_context, krb5_timestamp); #endif /* * Solaris Kerberos * The following two functions are needed for better realm * determination based on the DNS domain name. */ krb5_error_code krb5int_lookup_host(int , const char *, char **); krb5_error_code krb5int_domain_get_realm(krb5_context, const char *, char **); krb5_error_code krb5int_fqdn_get_realm(krb5_context, const char *, char **); krb5_error_code krb5int_init_context_kdc(krb5_context *); krb5_error_code krb5_os_init_context (krb5_context, krb5_boolean); void krb5_os_free_context (krb5_context); /* This function is needed by KfM's KerberosPreferences API * because it needs to be able to specify "secure" */ #ifndef _KERNEL krb5_error_code os_get_default_config_files (profile_filespec_t **pfiles, krb5_boolean secure); #endif krb5_error_code krb5_os_hostaddr (krb5_context, const char *, krb5_address ***); #ifndef _KERNEL /* N.B.: You need to include fake-addrinfo.h *before* k5-int.h if you're going to use this structure. */ struct addrlist { struct { #ifdef FAI_DEFINED struct addrinfo *ai; #else struct undefined_addrinfo *ai; #endif void (*freefn)(void *); void *data; } *addrs; int naddrs; int space; }; #define ADDRLIST_INIT { 0, 0, 0 } extern void krb5int_free_addrlist (struct addrlist *); extern int krb5int_grow_addrlist (struct addrlist *, int); extern int krb5int_add_host_to_list (struct addrlist *, const char *, int, int, int, int); #include krb5_error_code krb5int_locate_server (krb5_context, const krb5_data *realm, struct addrlist *, enum locate_service_type svc, int sockettype, int family); #endif /* _KERNEL */ /* new encryption provider api */ struct krb5_enc_provider { /* keybytes is the input size to make_key; keylength is the output size */ size_t block_size, keybytes, keylength; /* cipher-state == 0 fresh state thrown away at end */ krb5_error_code (*encrypt) ( krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output); krb5_error_code (*decrypt) ( krb5_context context, krb5_const krb5_keyblock *key, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output); krb5_error_code (*make_key) (krb5_context, krb5_const krb5_data *, krb5_keyblock *); krb5_error_code (*init_state) (krb5_context, const krb5_keyblock *, krb5_keyusage, krb5_data *); krb5_error_code (*free_state) (krb5_context, krb5_data *); }; struct krb5_hash_provider { size_t hashsize, blocksize; /* this takes multiple inputs to avoid lots of copying. */ krb5_error_code (*hash) (krb5_context context, unsigned int icount, krb5_const krb5_data *input, krb5_data *output); }; struct krb5_keyhash_provider { size_t hashsize; krb5_error_code (*hash) ( krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage keyusage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output); krb5_error_code (*verify) ( krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage keyusage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_const krb5_data *hash, krb5_boolean *valid); }; typedef void (*krb5_encrypt_length_func) (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t inputlen, size_t *length); typedef krb5_error_code (*krb5_crypt_func) ( krb5_context context, krb5_const struct krb5_enc_provider *enc, krb5_const struct krb5_hash_provider *hash, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output); #ifndef _KERNEL typedef krb5_error_code (*krb5_str2key_func) ( krb5_context context, krb5_const struct krb5_enc_provider *enc, krb5_const krb5_data *string, krb5_const krb5_data *salt, krb5_const krb5_data *params, krb5_keyblock *key); #endif /* _KERNEL */ typedef krb5_error_code (*krb5_prf_func)( const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, const krb5_data *in, krb5_data *out); struct krb5_keytypes { krb5_enctype etype; char *in_string; char *out_string; const struct krb5_enc_provider *enc; const struct krb5_hash_provider *hash; krb5_encrypt_length_func encrypt_len; krb5_crypt_func encrypt; krb5_crypt_func decrypt; krb5_cksumtype required_ctype; #ifndef _KERNEL /* Solaris Kerberos: strings to key conversion not done in the kernel */ krb5_str2key_func str2key; #else /* _KERNEL */ char *mt_e_name; char *mt_h_name; crypto_mech_type_t kef_cipher_mt; crypto_mech_type_t kef_hash_mt; #endif /* _KERNEL */ }; struct krb5_cksumtypes { krb5_cksumtype ctype; unsigned int flags; char *in_string; char *out_string; /* if the hash is keyed, this is the etype it is keyed with. Actually, it can be keyed by any etype which has the same enc_provider as the specified etype. DERIVE checksums can be keyed with any valid etype. */ krb5_enctype keyed_etype; /* I can't statically initialize a union, so I'm just going to use two pointers here. The keyhash is used if non-NULL. If NULL, then HMAC/hash with derived keys is used if the relevant flag is set. Otherwise, a non-keyed hash is computed. This is all kind of messy, but so is the krb5 api. */ const struct krb5_keyhash_provider *keyhash; const struct krb5_hash_provider *hash; /* This just gets uglier and uglier. In the key derivation case, we produce an hmac. To make the hmac code work, we can't hack the output size indicated by the hash provider, but we may want a truncated hmac. If we want truncation, this is the number of bytes we truncate to; it should be 0 otherwise. */ unsigned int trunc_size; #ifdef _KERNEL char *mt_c_name; crypto_mech_type_t kef_cksum_mt; #endif /* _KERNEL */ }; #define KRB5_CKSUMFLAG_DERIVE 0x0001 #define KRB5_CKSUMFLAG_NOT_COLL_PROOF 0x0002 /* * in here to deal with stuff from lib/crypto */ void krb5_nfold (unsigned int inbits, const unsigned char *in, unsigned int outbits, unsigned char *out); krb5_error_code krb5int_pbkdf2_hmac_sha1 (krb5_context, const krb5_data *, unsigned long, krb5_enctype, const krb5_data *, const krb5_data *); /* Make this a function eventually? */ #ifdef _WIN32 # define krb5int_zap_data(ptr, len) SecureZeroMemory(ptr, len) #elif defined(__palmos__) && !defined(__GNUC__) /* CodeWarrior 8.3 complains about passing a pointer to volatile in to memset. On the other hand, we probably want it for gcc. */ # define krb5int_zap_data(ptr, len) memset(ptr, 0, len) #else # define krb5int_zap_data(ptr, len) memset((void *)ptr, 0, len) # if defined(__GNUC__) && defined(__GLIBC__) /* GNU libc generates multiple bogus initialization warnings if we pass memset a volatile pointer. The compiler should do well enough with memset even without GNU libc's attempt at optimization. */ # undef memset # endif #endif /* WIN32 */ #define zap(p,l) krb5int_zap_data(p,l) krb5_error_code krb5int_des_init_state ( krb5_context, const krb5_keyblock *, krb5_keyusage, krb5_data *); krb5_error_code krb5int_c_mandatory_cksumtype( krb5_context, krb5_enctype, krb5_cksumtype *); /* * normally to free a cipher_state you can just memset the length to zero and * free it. */ krb5_error_code krb5int_default_free_state (krb5_context, krb5_data *); /* * Combine two keys (normally used by the hardware preauth mechanism) */ krb5_error_code krb5int_c_combine_keys (krb5_context context, krb5_keyblock *key1, krb5_keyblock *key2, krb5_keyblock *outkey); #ifdef _KERNEL int k5_ef_crypto( const char *, char *, long, krb5_keyblock *, const krb5_data *, int); krb5_error_code krb5_hmac(krb5_context, const krb5_keyblock *, krb5_const krb5_data *, krb5_data *); #else krb5_error_code krb5_hmac (krb5_context, krb5_const struct krb5_hash_provider *, krb5_const krb5_keyblock *, krb5_const unsigned int, krb5_const krb5_data *, krb5_data *); #endif /* _KERNEL */ /* * These declarations are here, so both krb5 and k5crypto * can get to them. * krb5 needs to get to them so it can make them available to libgssapi. */ extern const struct krb5_enc_provider krb5int_enc_arcfour; extern const struct krb5_hash_provider krb5int_hash_md5; /* #ifdef KRB5_OLD_CRYPTO XXX SUNW14resync */ krb5_error_code krb5_crypto_us_timeofday (krb5_int32 *, krb5_int32 *); #ifndef _KERNEL /* Solaris kerberos: for convenience */ time_t krb5int_gmt_mktime (struct tm *); #endif /* ! _KERNEL */ /* #endif KRB5_OLD_CRYPTO */ /* this helper fct is in libkrb5, but it makes sense declared here. */ krb5_error_code krb5_encrypt_helper (krb5_context context, const krb5_keyblock *key, krb5_keyusage keyusage, const krb5_data *plain, krb5_enc_data *cipher); /* * End "los-proto.h" */ /* * Begin "libos.h" */ #ifndef KRB5_LIBOS__ #define KRB5_LIBOS__ typedef struct _krb5_os_context { krb5_magic magic; krb5_int32 time_offset; krb5_int32 usec_offset; krb5_int32 os_flags; char * default_ccname; } *krb5_os_context; /* * Flags for the os_flags field * * KRB5_OS_TOFFSET_VALID means that the time offset fields are valid. * The intention is that this facility to correct the system clocks so * that they reflect the "real" time, for systems where for some * reason we can't set the system clock. Instead we calculate the * offset between the system time and real time, and store the offset * in the os context so that we can correct the system clock as necessary. * * KRB5_OS_TOFFSET_TIME means that the time offset fields should be * returned as the time by the krb5 time routines. This should only * be used for testing purposes (obviously!) */ #define KRB5_OS_TOFFSET_VALID 1 #define KRB5_OS_TOFFSET_TIME 2 /* lock mode flags */ #define KRB5_LOCKMODE_SHARED 0x0001 #define KRB5_LOCKMODE_EXCLUSIVE 0x0002 #define KRB5_LOCKMODE_DONTBLOCK 0x0004 #define KRB5_LOCKMODE_UNLOCK 0x0008 #endif /* KRB5_LIBOS__ */ /* * End "libos.h" */ /* * Define our view of the size of a DES key. */ #define KRB5_MIT_DES_KEYSIZE 8 /* * Define a couple of SHA1 constants */ #define SHS_DATASIZE 64 #define SHS_DIGESTSIZE 20 /* * Check if des_int.h has been included before us. If so, then check to see * that our view of the DES key size is the same as des_int.h's. */ #ifdef MIT_DES_KEYSIZE #if MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE error(MIT_DES_KEYSIZE does not equal KRB5_MIT_DES_KEYSIZE) #endif /* MIT_DES_KEYSIZE != KRB5_MIT_DES_KEYSIZE */ #endif /* MIT_DES_KEYSIZE */ #ifndef _KERNEL /* Solaris Kerberos: only define PROVIDE_DES3_CBC_SHA if the following are * defined. */ #define PROVIDE_DES3_CBC_SHA 1 #define PROVIDE_NIST_SHA 1 #endif /* !_KERNEL */ /* * Begin "preauth.h" * * (Originally written by Glen Machin at Sandia Labs.) */ /* * Sandia National Laboratories also makes no representations about the * suitability of the modifications, or additions to this software for * any purpose. It is provided "as is" without express or implied warranty. * */ #ifndef KRB5_PREAUTH__ #define KRB5_PREAUTH__ #include #define CLIENT_ROCK_MAGIC 0x4352434b /* This structure is passed into the client preauth functions and passed * back to the "get_data_proc" function so that it can locate the * requested information. It is opaque to the plugin code and can be * expanded in the future as new types of requests are defined which * may require other things to be passed through. */ typedef struct _krb5_preauth_client_rock { krb5_magic magic; krb5_kdc_rep *as_reply; } krb5_preauth_client_rock; /* This structure lets us keep track of all of the modules which are loaded, * turning the list of modules and their lists of implemented preauth types * into a single list which we can walk easily. */ typedef struct _krb5_preauth_context { int n_modules; struct _krb5_preauth_context_module { /* Which of the possibly more than one preauth types which the * module supports we're using at this point in the list. */ krb5_preauthtype pa_type; /* Encryption types which the client claims to support -- we * copy them directly into the krb5_kdc_req structure during * krb5_preauth_prepare_request(). */ krb5_enctype *enctypes; /* The plugin's per-plugin context and a function to clear it. */ void *plugin_context; preauth_client_plugin_fini_proc client_fini; /* The module's table, and some of its members, copied here for * convenience when we populated the list. */ struct krb5plugin_preauth_client_ftable_v1 *ftable; const char *name; int flags, use_count; preauth_client_process_proc client_process; preauth_client_tryagain_proc client_tryagain; preauth_client_supply_gic_opts_proc client_supply_gic_opts; preauth_client_request_init_proc client_req_init; preauth_client_request_fini_proc client_req_fini; /* The per-request context which the client_req_init() function * might allocate, which we'll need to clean up later by * calling the client_req_fini() function. */ void *request_context; /* A pointer to the request_context pointer. All modules within * a plugin will point at the request_context of the first * module within the plugin. */ void **request_context_pp; } *modules; } krb5_preauth_context; typedef struct _krb5_pa_enc_ts { krb5_timestamp patimestamp; krb5_int32 pausec; } krb5_pa_enc_ts; typedef struct _krb5_pa_for_user { krb5_principal user; krb5_checksum cksum; krb5_data auth_package; } krb5_pa_for_user; enum { KRB5_FAST_ARMOR_AP_REQUEST = 0x1 }; typedef struct _krb5_fast_armor { krb5_int32 armor_type; krb5_data armor_value; } krb5_fast_armor; typedef struct _krb5_fast_armored_req { krb5_magic magic; krb5_fast_armor *armor; krb5_checksum req_checksum; krb5_enc_data enc_part; } krb5_fast_armored_req; typedef struct _krb5_fast_req { krb5_magic magic; krb5_flags fast_options; /* padata from req_body is used*/ krb5_kdc_req *req_body; } krb5_fast_req; /* Bits 0-15 are critical in fast options.*/ #define UNSUPPORTED_CRITICAL_FAST_OPTIONS 0x00ff #define KRB5_FAST_OPTION_HIDE_CLIENT_NAMES 0x01 typedef struct _krb5_fast_finished { krb5_timestamp timestamp; krb5_int32 usec; krb5_principal client; krb5_checksum ticket_checksum; } krb5_fast_finished; typedef struct _krb5_fast_response { krb5_magic magic; krb5_pa_data **padata; krb5_keyblock *strengthen_key; krb5_fast_finished *finished; krb5_int32 nonce; } krb5_fast_response; typedef krb5_error_code (*krb5_preauth_obtain_proc) (krb5_context, krb5_pa_data *, krb5_etype_info, krb5_keyblock *, krb5_error_code ( * )(krb5_context, const krb5_enctype, krb5_data *, krb5_const_pointer, krb5_keyblock **), krb5_const_pointer, krb5_creds *, krb5_kdc_req *, krb5_pa_data **); typedef krb5_error_code (*krb5_preauth_process_proc) (krb5_context, krb5_pa_data *, krb5_kdc_req *, krb5_kdc_rep *, krb5_error_code ( * )(krb5_context, const krb5_enctype, krb5_data *, krb5_const_pointer, krb5_keyblock **), krb5_const_pointer, krb5_error_code ( * )(krb5_context, const krb5_keyblock *, krb5_const_pointer, krb5_kdc_rep * ), krb5_keyblock **, krb5_creds *, krb5_int32 *, krb5_int32 *); typedef struct _krb5_preauth_ops { krb5_magic magic; int type; int flags; krb5_preauth_obtain_proc obtain; krb5_preauth_process_proc process; } krb5_preauth_ops; krb5_error_code krb5_obtain_padata (krb5_context, krb5_pa_data **, krb5_error_code ( * )(krb5_context, const krb5_enctype, krb5_data *, krb5_const_pointer, krb5_keyblock **), krb5_const_pointer, krb5_creds *, krb5_kdc_req *); krb5_error_code krb5_process_padata (krb5_context, krb5_kdc_req *, krb5_kdc_rep *, krb5_error_code ( * )(krb5_context, const krb5_enctype, krb5_data *, krb5_const_pointer, krb5_keyblock **), krb5_const_pointer, krb5_error_code ( * )(krb5_context, const krb5_keyblock *, krb5_const_pointer, krb5_kdc_rep * ), krb5_keyblock **, krb5_creds *, krb5_int32 *); void krb5_free_etype_info (krb5_context, krb5_etype_info); /* * Preauthentication property flags */ #define KRB5_PREAUTH_FLAGS_ENCRYPT 0x00000001 #define KRB5_PREAUTH_FLAGS_HARDWARE 0x00000002 #endif /* KRB5_PREAUTH__ */ /* * End "preauth.h" */ /* * Extending the krb5_get_init_creds_opt structure. The original * krb5_get_init_creds_opt structure is defined publicly. The * new extended version is private. The original interface * assumed a pre-allocated structure which was passed to * krb5_get_init_creds_init(). The new interface assumes that * the caller will call krb5_get_init_creds_alloc() and * krb5_get_init_creds_free(). * * Callers MUST NOT call krb5_get_init_creds_init() after allocating an * opts structure using krb5_get_init_creds_alloc(). To do so will * introduce memory leaks. Unfortunately, there is no way to enforce * this behavior. * * Two private flags are added for backward compatibility. * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated * with the new krb5_get_init_creds_opt_alloc() function. * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended * structure is a shadow copy of an original krb5_get_init_creds_opt * structure. * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to * krb5int_gic_opt_to_opte(), the resulting extended structure should be * freed (using krb5_get_init_creds_free). Otherwise, the original * structure was already extended and there is no need to free it. */ #define KRB5_GET_INIT_CREDS_OPT_EXTENDED 0x80000000 #define KRB5_GET_INIT_CREDS_OPT_SHADOWED 0x40000000 #define krb5_gic_opt_is_extended(s) \ ((s) && ((s)->flags & KRB5_GET_INIT_CREDS_OPT_EXTENDED) ? 1 : 0) #define krb5_gic_opt_is_shadowed(s) \ ((s) && ((s)->flags & KRB5_GET_INIT_CREDS_OPT_SHADOWED) ? 1 : 0) typedef struct _krb5_gic_opt_private { int num_preauth_data; krb5_gic_opt_pa_data *preauth_data; } krb5_gic_opt_private; typedef struct _krb5_gic_opt_ext { krb5_flags flags; krb5_deltat tkt_life; krb5_deltat renew_life; int forwardable; int proxiable; krb5_enctype *etype_list; int etype_list_length; krb5_address **address_list; krb5_preauthtype *preauth_list; int preauth_list_length; krb5_data *salt; /* * Do not change anything above this point in this structure. * It is identical to the public krb5_get_init_creds_opt structure. * New members must be added below. */ krb5_gic_opt_private *opt_private; } krb5_gic_opt_ext; krb5_error_code krb5int_gic_opt_to_opte(krb5_context context, krb5_get_init_creds_opt *opt, krb5_gic_opt_ext **opte, unsigned int force, const char *where); krb5_error_code krb5int_copy_data_contents (krb5_context, const krb5_data *, krb5_data *); krb5_error_code krb5int_copy_data_contents_add0 (krb5_context, const krb5_data *, krb5_data *); #ifndef _KERNEL /* needed for lib/krb5/krb/ */ typedef krb5_error_code (*krb5_gic_get_as_key_fct) (krb5_context, krb5_principal, krb5_enctype, krb5_prompter_fct, void *prompter_data, krb5_data *salt, krb5_data *s2kparams, krb5_keyblock *as_key, void *gak_data); krb5_error_code KRB5_CALLCONV krb5_get_init_creds (krb5_context context, krb5_creds *creds, krb5_principal client, krb5_prompter_fct prompter, void *prompter_data, krb5_deltat start_time, char *in_tkt_service, krb5_gic_opt_ext *gic_options, krb5_gic_get_as_key_fct gak, void *gak_data, int *master, krb5_kdc_rep **as_reply); krb5_error_code krb5int_populate_gic_opt ( krb5_context, krb5_gic_opt_ext **, krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, krb5_creds *creds); krb5_error_code KRB5_CALLCONV krb5_do_preauth (krb5_context context, krb5_kdc_req *request, krb5_data *encoded_request_body, krb5_data *encoded_previous_request, krb5_pa_data **in_padata, krb5_pa_data ***out_padata, krb5_data *salt, krb5_data *s2kparams, krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data, krb5_preauth_client_rock *get_data_rock, krb5_gic_opt_ext *opte); krb5_error_code KRB5_CALLCONV krb5_do_preauth_tryagain (krb5_context context, krb5_kdc_req *request, krb5_data *encoded_request_body, krb5_data *encoded_previous_request, krb5_pa_data **in_padata, krb5_pa_data ***out_padata, krb5_error *err_reply, krb5_data *salt, krb5_data *s2kparams, krb5_enctype *etype, krb5_keyblock *as_key, krb5_prompter_fct prompter, void *prompter_data, krb5_gic_get_as_key_fct gak_fct, void *gak_data, krb5_preauth_client_rock *get_data_rock, krb5_gic_opt_ext *opte); void KRB5_CALLCONV krb5_init_preauth_context (krb5_context); void KRB5_CALLCONV krb5_free_preauth_context (krb5_context); void KRB5_CALLCONV krb5_clear_preauth_context_use_counts (krb5_context); void KRB5_CALLCONV krb5_preauth_prepare_request (krb5_context, krb5_gic_opt_ext *, krb5_kdc_req *); void KRB5_CALLCONV krb5_preauth_request_context_init (krb5_context); void KRB5_CALLCONV krb5_preauth_request_context_fini (krb5_context); #endif /* _KERNEL */ void KRB5_CALLCONV krb5_free_sam_challenge (krb5_context, krb5_sam_challenge * ); void KRB5_CALLCONV krb5_free_sam_challenge_2 (krb5_context, krb5_sam_challenge_2 * ); void KRB5_CALLCONV krb5_free_sam_challenge_2_body (krb5_context, krb5_sam_challenge_2_body *); void KRB5_CALLCONV krb5_free_sam_response (krb5_context, krb5_sam_response * ); void KRB5_CALLCONV krb5_free_sam_response_2 (krb5_context, krb5_sam_response_2 * ); void KRB5_CALLCONV krb5_free_predicted_sam_response (krb5_context, krb5_predicted_sam_response * ); void KRB5_CALLCONV krb5_free_enc_sam_response_enc (krb5_context, krb5_enc_sam_response_enc * ); void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2 (krb5_context, krb5_enc_sam_response_enc_2 * ); void KRB5_CALLCONV krb5_free_sam_challenge_contents (krb5_context, krb5_sam_challenge * ); void KRB5_CALLCONV krb5_free_sam_challenge_2_contents (krb5_context, krb5_sam_challenge_2 * ); void KRB5_CALLCONV krb5_free_sam_challenge_2_body_contents (krb5_context, krb5_sam_challenge_2_body * ); void KRB5_CALLCONV krb5_free_sam_response_contents (krb5_context, krb5_sam_response * ); void KRB5_CALLCONV krb5_free_sam_response_2_contents (krb5_context, krb5_sam_response_2 *); void KRB5_CALLCONV krb5_free_predicted_sam_response_contents (krb5_context, krb5_predicted_sam_response * ); void KRB5_CALLCONV krb5_free_enc_sam_response_enc_contents (krb5_context, krb5_enc_sam_response_enc * ); void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2_contents (krb5_context, krb5_enc_sam_response_enc_2 * ); void KRB5_CALLCONV krb5_free_pa_enc_ts (krb5_context, krb5_pa_enc_ts *); /* #include "krb5/wordsize.h" -- comes in through base-defs.h. */ #ifndef _KERNEL #include "com_err.h" #include #endif /* _KERNEL */ /* * Solaris Kerberos: moved from sendto_kdc.c so other code can reference */ #define DEFAULT_UDP_PREF_LIMIT 1465 #ifndef _KERNEL #include "profile.h" #include #endif /* _KERNEL */ #define KEY_CHANGED(k1, k2) \ (k1 == NULL || \ k1 != k2 || \ k1->enctype != k2->enctype || \ k1->length != k2->length || \ bcmp(k1->contents, k2->contents, k1->length)) #ifndef _KERNEL typedef struct _arcfour_ctx { CK_SESSION_HANDLE eSession; /* encrypt session handle */ CK_SESSION_HANDLE dSession; /* decrypt session handle */ CK_OBJECT_HANDLE eKey; /* encrypt key object */ CK_OBJECT_HANDLE dKey; /* decrype key object */ uchar_t initialized; }arcfour_ctx_rec; #endif /* !_KERNEL */ struct _krb5_context { krb5_magic magic; krb5_enctype *in_tkt_ktypes; unsigned int in_tkt_ktype_count; krb5_enctype *tgs_ktypes; unsigned int tgs_ktype_count; /* This used to be a void*, but since we always allocate them together (though in different source files), and the types are declared in the same header, might as well just combine them. The array[1] is so the existing code treating the field as a pointer will still work. For cleanliness, it should eventually get changed to a single element instead of an array. */ struct _krb5_os_context os_context[1]; char *default_realm; int ser_ctx_count; krb5_boolean profile_secure; void *ser_ctx; #ifndef _KERNEL profile_t profile; void *db_context; void *kdblog_context; /* allowable clock skew */ krb5_deltat clockskew; krb5_cksumtype kdc_req_sumtype; krb5_cksumtype default_ap_req_sumtype; krb5_cksumtype default_safe_sumtype; krb5_flags kdc_default_options; krb5_flags library_options; int fcc_default_format; int scc_default_format; krb5_prompt_type *prompt_types; /* Message size above which we'll try TCP first in send-to-kdc type code. Aside from the 2**16 size limit, we put no absolute limit on the UDP packet size. */ int udp_pref_limit; /* This is the tgs_ktypes list as read from the profile, or set to compiled-in defaults. The application code cannot override it. This is used for session keys for intermediate ticket-granting tickets used to acquire the requested ticket (the session key of which may be constrained by tgs_ktypes above). */ krb5_enctype *conf_tgs_ktypes; int conf_tgs_ktypes_count; /* Use the _configured version? */ krb5_boolean use_conf_ktypes; #ifdef KRB5_DNS_LOOKUP krb5_boolean profile_in_memory; #endif /* KRB5_DNS_LOOKUP */ /* locate_kdc module stuff */ struct plugin_dir_handle libkrb5_plugins; struct krb5plugin_service_locate_ftable *vtbl; void (**locate_fptrs)(void); pid_t pid; /* fork safety: PID of process that did last PKCS11 init */ /* Solaris Kerberos: handles for PKCS#11 crypto */ /* * Warning, do not access hSession directly as this is not fork() safe. * Instead use the krb_ctx_hSession() macro below. */ CK_SESSION_HANDLE hSession; int cryptoki_initialized; /* arcfour_ctx: used only for rcmd stuff so no fork safety issues apply */ arcfour_ctx_rec arcfour_ctx; /* preauth module stuff */ struct plugin_dir_handle preauth_plugins; krb5_preauth_context *preauth_context; /* error detail info */ struct errinfo err; #else /* ! KERNEL */ crypto_mech_type_t kef_cipher_mt; crypto_mech_type_t kef_hash_mt; crypto_mech_type_t kef_cksum_mt; #endif /* ! KERNEL */ }; #ifndef _KERNEL extern pid_t __krb5_current_pid; CK_SESSION_HANDLE krb5_reinit_ef_handle(krb5_context); /* * fork safety: barring the ef_init code, every other function must use the * krb_ctx_hSession() macro to access the hSession field in a krb context. * Note, if the pid of the krb ctx == the current global pid then it is safe to * use the ctx hSession otherwise it needs to be re-inited before it is returned * to the caller. */ #define krb_ctx_hSession(ctx) \ ((ctx)->pid == __krb5_current_pid) ? (ctx)->hSession : krb5_reinit_ef_handle((ctx)) #endif #define MD5_CKSUM_LENGTH 16 #define RSA_MD5_CKSUM_LENGTH 16 #define MD5_BLOCKSIZE 64 /* * Solaris Kerberos: * This next section of prototypes and constants * are all unique to the Solaris Kerberos implementation. * Because Solaris uses the native encryption framework * to provide crypto support, the following routines * are needed to support this system. */ /* * Begin Solaris Crypto Prototypes */ /* * define constants that are used for creating the constant * which is used to make derived keys. */ #define DK_ENCR_KEY_BYTE 0xAA #define DK_HASH_KEY_BYTE 0x55 #define DK_CKSUM_KEY_BYTE 0x99 int init_derived_keydata(krb5_context, const struct krb5_enc_provider *, krb5_keyblock *, krb5_keyusage, krb5_keyblock **, krb5_keyblock **); krb5_error_code add_derived_key(krb5_keyblock *, krb5_keyusage, uchar_t, krb5_keyblock *); krb5_keyblock *find_derived_key(krb5_keyusage, uchar_t, krb5_keyblock *); krb5_keyblock *krb5_create_derived_keyblock(int); #ifdef _KERNEL int k5_ef_hash(krb5_context, int, const krb5_data *, krb5_data *); int k5_ef_mac(krb5_context, krb5_keyblock *, krb5_data *, const krb5_data *, krb5_data *); void make_kef_key(krb5_keyblock *); int init_key_kef(crypto_mech_type_t, krb5_keyblock *); int update_key_template(krb5_keyblock *); void setup_kef_keytypes(); void setup_kef_cksumtypes(); crypto_mech_type_t get_cipher_mech_type(krb5_context, krb5_keyblock *); crypto_mech_type_t get_hash_mech_type(krb5_context, krb5_keyblock *); #else /* * This structure is used to map Kerberos supported OID's, * to PKCS11 mechanisms */ #define USE_ENCR 0x01 #define USE_HASH 0x02 typedef struct krb5_mech_2_pkcs { uchar_t flags; CK_MECHANISM_TYPE enc_algo; CK_MECHANISM_TYPE hash_algo; CK_MECHANISM_TYPE str2key_algo; } KRB5_MECH_TO_PKCS; #define ENC_DEFINED(x) (((x).flags & USE_ENCR)) #define HASH_DEFINED(x) (((x).flags & USE_HASH)) extern CK_RV get_algo(krb5_enctype etype, KRB5_MECH_TO_PKCS * algos); extern CK_RV get_key_type (krb5_enctype etype, CK_KEY_TYPE * keyType); extern krb5_error_code slot_supports_krb5 (CK_SLOT_ID_PTR slotid); krb5_error_code init_key_uef(CK_SESSION_HANDLE, krb5_keyblock *); krb5_error_code k5_ef_hash(krb5_context, CK_MECHANISM *, unsigned int, const krb5_data *, krb5_data *); krb5_error_code k5_ef_mac(krb5_context context, krb5_keyblock *key, krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output); #endif /* !_KERNEL */ krb5_error_code derive_3des_keys(krb5_context, struct krb5_enc_provider *, krb5_keyblock *, krb5_keyusage, krb5_keyblock *, krb5_keyblock *); /* * End Solaris Crypto Prototypes */ #define KRB5_LIBOPT_SYNC_KDCTIME 0x0001 /* internal message representations */ typedef struct _krb5_safe { krb5_magic magic; krb5_data user_data; /* user data */ krb5_timestamp timestamp; /* client time, optional */ krb5_int32 usec; /* microsecond portion of time, optional */ krb5_ui_4 seq_number; /* sequence #, optional */ krb5_address *s_address; /* sender address */ krb5_address *r_address; /* recipient address, optional */ krb5_checksum *checksum; /* data integrity checksum */ } krb5_safe; typedef struct _krb5_priv { krb5_magic magic; krb5_enc_data enc_part; /* encrypted part */ } krb5_priv; typedef struct _krb5_priv_enc_part { krb5_magic magic; krb5_data user_data; /* user data */ krb5_timestamp timestamp; /* client time, optional */ krb5_int32 usec; /* microsecond portion of time, opt. */ krb5_ui_4 seq_number; /* sequence #, optional */ krb5_address *s_address; /* sender address */ krb5_address *r_address; /* recipient address, optional */ } krb5_priv_enc_part; void KRB5_CALLCONV krb5_free_safe (krb5_context, krb5_safe * ); void KRB5_CALLCONV krb5_free_priv (krb5_context, krb5_priv * ); void KRB5_CALLCONV krb5_free_priv_enc_part (krb5_context, krb5_priv_enc_part * ); /* * Begin "asn1.h" */ #ifndef KRB5_ASN1__ #define KRB5_ASN1__ /* ASN.1 encoding knowledge; KEEP IN SYNC WITH ASN.1 defs! */ /* here we use some knowledge of ASN.1 encodings */ /* Ticket is APPLICATION 1. Authenticator is APPLICATION 2. AS_REQ is APPLICATION 10. AS_REP is APPLICATION 11. TGS_REQ is APPLICATION 12. TGS_REP is APPLICATION 13. AP_REQ is APPLICATION 14. AP_REP is APPLICATION 15. KRB_SAFE is APPLICATION 20. KRB_PRIV is APPLICATION 21. KRB_CRED is APPLICATION 22. EncASRepPart is APPLICATION 25. EncTGSRepPart is APPLICATION 26. EncAPRepPart is APPLICATION 27. EncKrbPrivPart is APPLICATION 28. EncKrbCredPart is APPLICATION 29. KRB_ERROR is APPLICATION 30. */ /* allow either constructed or primitive encoding, so check for bit 6 set or reset */ #define krb5_is_krb_ticket(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x61 ||\ (dat)->data[0] == 0x41)) #define krb5_is_krb_authenticator(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x62 ||\ (dat)->data[0] == 0x42)) #define krb5_is_as_req(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6a ||\ (dat)->data[0] == 0x4a)) #define krb5_is_as_rep(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6b ||\ (dat)->data[0] == 0x4b)) #define krb5_is_tgs_req(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6c ||\ (dat)->data[0] == 0x4c)) #define krb5_is_tgs_rep(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6d ||\ (dat)->data[0] == 0x4d)) #define krb5_is_ap_req(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6e ||\ (dat)->data[0] == 0x4e)) #define krb5_is_ap_rep(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x6f ||\ (dat)->data[0] == 0x4f)) #define krb5_is_krb_safe(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x74 ||\ (dat)->data[0] == 0x54)) #define krb5_is_krb_priv(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x75 ||\ (dat)->data[0] == 0x55)) #define krb5_is_krb_cred(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x76 ||\ (dat)->data[0] == 0x56)) #define krb5_is_krb_enc_as_rep_part(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x79 ||\ (dat)->data[0] == 0x59)) #define krb5_is_krb_enc_tgs_rep_part(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x7a ||\ (dat)->data[0] == 0x5a)) #define krb5_is_krb_enc_ap_rep_part(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x7b ||\ (dat)->data[0] == 0x5b)) #define krb5_is_krb_enc_krb_priv_part(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x7c ||\ (dat)->data[0] == 0x5c)) #define krb5_is_krb_enc_krb_cred_part(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x7d ||\ (dat)->data[0] == 0x5d)) #define krb5_is_krb_error(dat)\ ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\ (dat)->data[0] == 0x5e)) /************************************************************************* * Prototypes for krb5_encode.c *************************************************************************/ /* krb5_error_code encode_krb5_structure(const krb5_structure *rep, krb5_data **code); modifies *code effects Returns the ASN.1 encoding of *rep in **code. Returns ASN1_MISSING_FIELD if a required field is emtpy in *rep. Returns ENOMEM if memory runs out. */ krb5_error_code encode_krb5_authenticator (const krb5_authenticator *rep, krb5_data **code); krb5_error_code encode_krb5_ticket (const krb5_ticket *rep, krb5_data **code); krb5_error_code encode_krb5_encryption_key (const krb5_keyblock *rep, krb5_data **code); krb5_error_code encode_krb5_enc_tkt_part (const krb5_enc_tkt_part *rep, krb5_data **code); krb5_error_code encode_krb5_enc_kdc_rep_part (const krb5_enc_kdc_rep_part *rep, krb5_data **code); /* yes, the translation is identical to that used for KDC__REP */ krb5_error_code encode_krb5_as_rep (const krb5_kdc_rep *rep, krb5_data **code); /* yes, the translation is identical to that used for KDC__REP */ krb5_error_code encode_krb5_tgs_rep (const krb5_kdc_rep *rep, krb5_data **code); krb5_error_code encode_krb5_ap_req (const krb5_ap_req *rep, krb5_data **code); krb5_error_code encode_krb5_ap_rep (const krb5_ap_rep *rep, krb5_data **code); krb5_error_code encode_krb5_ap_rep_enc_part (const krb5_ap_rep_enc_part *rep, krb5_data **code); krb5_error_code encode_krb5_as_req (const krb5_kdc_req *rep, krb5_data **code); krb5_error_code encode_krb5_tgs_req (const krb5_kdc_req *rep, krb5_data **code); krb5_error_code encode_krb5_kdc_req_body (const krb5_kdc_req *rep, krb5_data **code); krb5_error_code encode_krb5_safe (const krb5_safe *rep, krb5_data **code); struct krb5_safe_with_body { krb5_safe *safe; krb5_data *body; }; krb5_error_code encode_krb5_safe_with_body (const struct krb5_safe_with_body *rep, krb5_data **code); krb5_error_code encode_krb5_priv (const krb5_priv *rep, krb5_data **code); krb5_error_code encode_krb5_enc_priv_part (const krb5_priv_enc_part *rep, krb5_data **code); krb5_error_code encode_krb5_cred (const krb5_cred *rep, krb5_data **code); krb5_error_code encode_krb5_enc_cred_part (const krb5_cred_enc_part *rep, krb5_data **code); krb5_error_code encode_krb5_error (const krb5_error *rep, krb5_data **code); krb5_error_code encode_krb5_authdata (krb5_authdata *const *rep, krb5_data **code); krb5_error_code encode_krb5_authdata_elt (const krb5_authdata *rep, krb5_data **code); krb5_error_code encode_krb5_pwd_sequence (const passwd_phrase_element *rep, krb5_data **code); krb5_error_code encode_krb5_pwd_data (const krb5_pwd_data *rep, krb5_data **code); krb5_error_code encode_krb5_padata_sequence (krb5_pa_data *const *rep, krb5_data **code); krb5_error_code encode_krb5_alt_method (const krb5_alt_method *, krb5_data **code); krb5_error_code encode_krb5_etype_info (krb5_etype_info_entry *const *, krb5_data **code); krb5_error_code encode_krb5_etype_info2 (krb5_etype_info_entry *const *, krb5_data **code); krb5_error_code encode_krb5_enc_data (const krb5_enc_data *, krb5_data **); krb5_error_code encode_krb5_pa_enc_ts (const krb5_pa_enc_ts *, krb5_data **); krb5_error_code encode_krb5_sam_challenge (const krb5_sam_challenge * , krb5_data **); krb5_error_code encode_krb5_sam_key (const krb5_sam_key * , krb5_data **); krb5_error_code encode_krb5_enc_sam_response_enc (const krb5_enc_sam_response_enc * , krb5_data **); krb5_error_code encode_krb5_sam_response (const krb5_sam_response * , krb5_data **); krb5_error_code encode_krb5_sam_challenge_2 (const krb5_sam_challenge_2 * , krb5_data **); krb5_error_code encode_krb5_sam_challenge_2_body (const krb5_sam_challenge_2_body * , krb5_data **); krb5_error_code encode_krb5_enc_sam_response_enc_2 (const krb5_enc_sam_response_enc_2 * , krb5_data **); krb5_error_code encode_krb5_sam_response_2 (const krb5_sam_response_2 * , krb5_data **); krb5_error_code encode_krb5_predicted_sam_response (const krb5_predicted_sam_response * , krb5_data **); struct krb5_setpw_req { krb5_principal target; krb5_data password; }; krb5_error_code encode_krb5_setpw_req (const struct krb5_setpw_req *rep, krb5_data **code); /************************************************************************* * End of prototypes for krb5_encode.c *************************************************************************/ krb5_error_code decode_krb5_sam_challenge (const krb5_data *, krb5_sam_challenge **); krb5_error_code decode_krb5_enc_sam_key (const krb5_data *, krb5_sam_key **); krb5_error_code decode_krb5_enc_sam_response_enc (const krb5_data *, krb5_enc_sam_response_enc **); krb5_error_code decode_krb5_sam_response (const krb5_data *, krb5_sam_response **); krb5_error_code decode_krb5_predicted_sam_response (const krb5_data *, krb5_predicted_sam_response **); krb5_error_code decode_krb5_sam_challenge_2 (const krb5_data *, krb5_sam_challenge_2 **); krb5_error_code decode_krb5_sam_challenge_2_body (const krb5_data *, krb5_sam_challenge_2_body **); krb5_error_code decode_krb5_enc_sam_response_enc_2 (const krb5_data *, krb5_enc_sam_response_enc_2 **); krb5_error_code decode_krb5_sam_response_2 (const krb5_data *, krb5_sam_response_2 **); /************************************************************************* * Prototypes for krb5_decode.c *************************************************************************/ krb5_error_code krb5_validate_times (krb5_context, krb5_ticket_times *); /* krb5_error_code decode_krb5_structure(const krb5_data *code, krb5_structure **rep); requires Expects **rep to not have been allocated; a new *rep is allocated regardless of the old value. effects Decodes *code into **rep. Returns ENOMEM if memory is exhausted. Returns asn1 and krb5 errors. */ krb5_error_code decode_krb5_authenticator (const krb5_data *code, krb5_authenticator **rep); krb5_error_code decode_krb5_ticket (const krb5_data *code, krb5_ticket **rep); krb5_error_code decode_krb5_encryption_key (const krb5_data *output, krb5_keyblock **rep); krb5_error_code decode_krb5_enc_tkt_part (const krb5_data *output, krb5_enc_tkt_part **rep); krb5_error_code decode_krb5_enc_kdc_rep_part (const krb5_data *output, krb5_enc_kdc_rep_part **rep); krb5_error_code decode_krb5_as_rep (const krb5_data *output, krb5_kdc_rep **rep); krb5_error_code decode_krb5_tgs_rep (const krb5_data *output, krb5_kdc_rep **rep); krb5_error_code decode_krb5_ap_req (const krb5_data *output, krb5_ap_req **rep); krb5_error_code decode_krb5_ap_rep (const krb5_data *output, krb5_ap_rep **rep); krb5_error_code decode_krb5_ap_rep_enc_part (const krb5_data *output, krb5_ap_rep_enc_part **rep); krb5_error_code decode_krb5_as_req (const krb5_data *output, krb5_kdc_req **rep); krb5_error_code decode_krb5_tgs_req (const krb5_data *output, krb5_kdc_req **rep); krb5_error_code decode_krb5_kdc_req_body (const krb5_data *output, krb5_kdc_req **rep); krb5_error_code decode_krb5_safe (const krb5_data *output, krb5_safe **rep); krb5_error_code decode_krb5_safe_with_body (const krb5_data *output, krb5_safe **rep, krb5_data *body); krb5_error_code decode_krb5_priv (const krb5_data *output, krb5_priv **rep); krb5_error_code decode_krb5_enc_priv_part (const krb5_data *output, krb5_priv_enc_part **rep); krb5_error_code decode_krb5_cred (const krb5_data *output, krb5_cred **rep); krb5_error_code decode_krb5_enc_cred_part (const krb5_data *output, krb5_cred_enc_part **rep); krb5_error_code decode_krb5_error (const krb5_data *output, krb5_error **rep); krb5_error_code decode_krb5_authdata (const krb5_data *output, krb5_authdata ***rep); krb5_error_code decode_krb5_pwd_sequence (const krb5_data *output, passwd_phrase_element **rep); krb5_error_code decode_krb5_pwd_data (const krb5_data *output, krb5_pwd_data **rep); krb5_error_code decode_krb5_padata_sequence (const krb5_data *output, krb5_pa_data ***rep); krb5_error_code decode_krb5_alt_method (const krb5_data *output, krb5_alt_method **rep); krb5_error_code decode_krb5_etype_info (const krb5_data *output, krb5_etype_info_entry ***rep); krb5_error_code decode_krb5_etype_info2 (const krb5_data *output, krb5_etype_info_entry ***rep); krb5_error_code decode_krb5_enc_data (const krb5_data *output, krb5_enc_data **rep); krb5_error_code decode_krb5_pa_enc_ts (const krb5_data *output, krb5_pa_enc_ts **rep); krb5_error_code decode_krb5_sam_key (const krb5_data *, krb5_sam_key **); struct _krb5_key_data; /* kdb.h */ krb5_error_code krb5int_ldap_encode_sequence_of_keys (struct _krb5_key_data *key_data, krb5_int16 n_key_data, krb5_int32 mkvno, krb5_data **code); krb5_error_code krb5int_ldap_decode_sequence_of_keys (krb5_data *in, struct _krb5_key_data **out, krb5_int16 *n_key_data, int *mkvno); /************************************************************************* * End of prototypes for krb5_decode.c *************************************************************************/ #endif /* KRB5_ASN1__ */ /* * End "asn1.h" */ /* * Internal krb5 library routines */ krb5_error_code krb5_encrypt_tkt_part (krb5_context, const krb5_keyblock *, krb5_ticket * ); krb5_error_code krb5_encode_kdc_rep (krb5_context, const krb5_msgtype, const krb5_enc_kdc_rep_part *, int using_subkey, const krb5_keyblock *, krb5_kdc_rep *, krb5_data ** ); krb5_boolean krb5int_auth_con_chkseqnum (krb5_context ctx, krb5_auth_context ac, krb5_ui_4 in_seq); /* * [De]Serialization Handle and operations. */ struct __krb5_serializer { krb5_magic odtype; krb5_error_code (*sizer) (krb5_context, krb5_pointer, size_t *); krb5_error_code (*externalizer) (krb5_context, krb5_pointer, krb5_octet **, size_t *); krb5_error_code (*internalizer) (krb5_context, krb5_pointer *, krb5_octet **, size_t *); }; typedef const struct __krb5_serializer * krb5_ser_handle; typedef struct __krb5_serializer krb5_ser_entry; krb5_ser_handle krb5_find_serializer (krb5_context, krb5_magic); krb5_error_code krb5_register_serializer (krb5_context, const krb5_ser_entry *); /* Determine the external size of a particular opaque structure */ krb5_error_code KRB5_CALLCONV krb5_size_opaque (krb5_context, krb5_magic, krb5_pointer, size_t *); /* Serialize the structure into a buffer */ krb5_error_code KRB5_CALLCONV krb5_externalize_opaque (krb5_context, krb5_magic, krb5_pointer, krb5_octet **, size_t *); /* Deserialize the structure from a buffer */ krb5_error_code KRB5_CALLCONV krb5_internalize_opaque (krb5_context, krb5_magic, krb5_pointer *, krb5_octet **, size_t *); /* Serialize data into a buffer */ krb5_error_code krb5_externalize_data (krb5_context, krb5_pointer, krb5_octet **, size_t *); /* * Initialization routines. */ /* Initialize serialization for krb5_[os_]context */ krb5_error_code KRB5_CALLCONV krb5_ser_context_init (krb5_context); /* Initialize serialization for krb5_auth_context */ krb5_error_code KRB5_CALLCONV krb5_ser_auth_context_init (krb5_context); /* Initialize serialization for krb5_keytab */ krb5_error_code KRB5_CALLCONV krb5_ser_keytab_init (krb5_context); /* Initialize serialization for krb5_ccache */ krb5_error_code KRB5_CALLCONV krb5_ser_ccache_init (krb5_context); /* Initialize serialization for krb5_rcache */ krb5_error_code KRB5_CALLCONV krb5_ser_rcache_init (krb5_context); /* [De]serialize 4-byte integer */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_int32 (krb5_int32, krb5_octet **, size_t *); krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int32 (krb5_int32 *, krb5_octet **, size_t *); /* [De]serialize 8-byte integer */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_int64 (krb5_int64, krb5_octet **, size_t *); krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int64 (krb5_int64 *, krb5_octet **, size_t *); /* [De]serialize byte string */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_bytes (krb5_octet *, size_t, krb5_octet **, size_t *); krb5_error_code KRB5_CALLCONV krb5_ser_unpack_bytes (krb5_octet *, size_t, krb5_octet **, size_t *); krb5_error_code KRB5_CALLCONV krb5int_cc_default (krb5_context, krb5_ccache *); krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred_default (krb5_context, krb5_ccache, krb5_flags, krb5_creds *, krb5_creds *); krb5_boolean KRB5_CALLCONV krb5_creds_compare (krb5_context in_context, krb5_creds *in_creds, krb5_creds *in_compare_creds); void krb5int_set_prompt_types (krb5_context, krb5_prompt_type *); krb5_error_code krb5int_generate_and_save_subkey (krb5_context, krb5_auth_context, krb5_keyblock * /* Old keyblock, not new! */); /* set and change password helpers */ krb5_error_code krb5int_mk_chpw_req (krb5_context context, krb5_auth_context auth_context, krb5_data *ap_req, char *passwd, krb5_data *packet); krb5_error_code krb5int_rd_chpw_rep (krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data); krb5_error_code KRB5_CALLCONV krb5_chpw_result_code_string (krb5_context context, int result_code, char **result_codestr); krb5_error_code krb5int_mk_setpw_req (krb5_context context, krb5_auth_context auth_context, krb5_data *ap_req, krb5_principal targetprinc, char *passwd, krb5_data *packet); krb5_error_code krb5int_rd_setpw_rep (krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data); krb5_error_code krb5int_setpw_result_code_string (krb5_context context, int result_code, const char **result_codestr); struct srv_dns_entry { struct srv_dns_entry *next; int priority; int weight; unsigned short port; char *host; }; #ifdef KRB5_DNS_LOOKUP krb5_error_code krb5int_make_srv_query_realm(const krb5_data *realm, const char *service, const char *protocol, struct srv_dns_entry **answers); void krb5int_free_srv_dns_data(struct srv_dns_entry *); #endif /* * Convenience function for structure magic number */ #define KRB5_VERIFY_MAGIC(structure,magic_number) \ if ((structure)->magic != (magic_number)) return (magic_number); /* SUNW14resync XXX - see k5-util.h */ #if 0 int krb5_seteuid (int); #endif char * krb5_getenv(const char *); int krb5_setenv (const char *, const char *, int); void krb5_unsetenv (const char *); /* SUNW14resync - (from here to EOF) not sure if we need this but will add it for future resync sake */ /* To keep happy libraries which are (for now) accessing internal stuff */ /* Make sure to increment by one when changing the struct */ #define KRB5INT_ACCESS_STRUCT_VERSION 12 #ifndef ANAME_SZ struct ktext; /* from krb.h, for krb524 support */ #endif typedef struct _krb5int_access { /* crypto stuff */ const struct krb5_hash_provider *md5_hash_provider; const struct krb5_enc_provider *arcfour_enc_provider; krb5_error_code (* krb5_hmac) (krb5_context, const struct krb5_hash_provider *hash, const krb5_keyblock *key, unsigned int icount, const krb5_data *input, krb5_data *output); /* service location and communication */ #ifndef _KERNEL krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg, const struct addrlist *, struct sendto_callback_info*, krb5_data *reply, struct sockaddr *, socklen_t *,struct sockaddr *, socklen_t *, int *, int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data); krb5_error_code (*add_host_to_list)(struct addrlist *lp, const char *hostname, int port, int secport, int socktype, int family); void (*free_addrlist) (struct addrlist *); #endif /* _KERNEL */ krb5_error_code (*make_srv_query_realm)(const krb5_data *realm, const char *service, const char *protocol, struct srv_dns_entry **answers); void (*free_srv_dns_data)(struct srv_dns_entry *); int (*use_dns_kdc)(krb5_context); krb5_error_code (*clean_hostname)(krb5_context, const char *, char *, size_t); /* krb4 compatibility stuff -- may be null if not enabled */ krb5_int32 (*krb_life_to_time)(krb5_int32, int); int (*krb_time_to_life)(krb5_int32, krb5_int32); int (*krb524_encode_v4tkt)(struct ktext *, char *, unsigned int *); krb5_error_code (*krb5int_c_mandatory_cksumtype) (krb5_context, krb5_enctype, krb5_cksumtype *); krb5_error_code (KRB5_CALLCONV *krb5_ser_pack_int64) (krb5_int64, krb5_octet **, size_t *); krb5_error_code (KRB5_CALLCONV *krb5_ser_unpack_int64) (krb5_int64 *, krb5_octet **, size_t *); /* Used for KDB LDAP back end. */ krb5_error_code (*asn1_ldap_encode_sequence_of_keys) (struct _krb5_key_data *key_data, krb5_int16 n_key_data, krb5_int32 mkvno, krb5_data **code); krb5_error_code (*asn1_ldap_decode_sequence_of_keys) (krb5_data *in, struct _krb5_key_data **out, krb5_int16 *n_key_data, int *mkvno); /* * pkinit asn.1 encode/decode functions */ krb5_error_code (*encode_krb5_auth_pack) (const krb5_auth_pack *rep, krb5_data **code); krb5_error_code (*encode_krb5_auth_pack_draft9) (const krb5_auth_pack_draft9 *rep, krb5_data **code); krb5_error_code (*encode_krb5_kdc_dh_key_info) (const krb5_kdc_dh_key_info *rep, krb5_data **code); krb5_error_code (*encode_krb5_pa_pk_as_rep) (const krb5_pa_pk_as_rep *rep, krb5_data **code); krb5_error_code (*encode_krb5_pa_pk_as_rep_draft9) (const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code); krb5_error_code (*encode_krb5_pa_pk_as_req) (const krb5_pa_pk_as_req *rep, krb5_data **code); krb5_error_code (*encode_krb5_pa_pk_as_req_draft9) (const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code); krb5_error_code (*encode_krb5_reply_key_pack) (const krb5_reply_key_pack *, krb5_data **code); krb5_error_code (*encode_krb5_reply_key_pack_draft9) (const krb5_reply_key_pack_draft9 *, krb5_data **code); krb5_error_code (*encode_krb5_td_dh_parameters) (const krb5_algorithm_identifier **, krb5_data **code); krb5_error_code (*encode_krb5_td_trusted_certifiers) (const krb5_external_principal_identifier **, krb5_data **code); krb5_error_code (*encode_krb5_typed_data) (const krb5_typed_data **, krb5_data **code); krb5_error_code (*decode_krb5_auth_pack) (const krb5_data *, krb5_auth_pack **); krb5_error_code (*decode_krb5_auth_pack_draft9) (const krb5_data *, krb5_auth_pack_draft9 **); krb5_error_code (*decode_krb5_pa_pk_as_req) (const krb5_data *, krb5_pa_pk_as_req **); krb5_error_code (*decode_krb5_pa_pk_as_req_draft9) (const krb5_data *, krb5_pa_pk_as_req_draft9 **); krb5_error_code (*decode_krb5_pa_pk_as_rep) (const krb5_data *, krb5_pa_pk_as_rep **); krb5_error_code (*decode_krb5_pa_pk_as_rep_draft9) (const krb5_data *, krb5_pa_pk_as_rep_draft9 **); krb5_error_code (*decode_krb5_kdc_dh_key_info) (const krb5_data *, krb5_kdc_dh_key_info **); krb5_error_code (*decode_krb5_principal_name) (const krb5_data *, krb5_principal_data **); krb5_error_code (*decode_krb5_reply_key_pack) (const krb5_data *, krb5_reply_key_pack **); krb5_error_code (*decode_krb5_reply_key_pack_draft9) (const krb5_data *, krb5_reply_key_pack_draft9 **); krb5_error_code (*decode_krb5_td_dh_parameters) (const krb5_data *, krb5_algorithm_identifier ***); krb5_error_code (*decode_krb5_td_trusted_certifiers) (const krb5_data *, krb5_external_principal_identifier ***); krb5_error_code (*decode_krb5_typed_data) (const krb5_data *, krb5_typed_data ***); krb5_error_code (*decode_krb5_as_req) (const krb5_data *output, krb5_kdc_req **rep); krb5_error_code (*encode_krb5_kdc_req_body) (const krb5_kdc_req *rep, krb5_data **code); void (KRB5_CALLCONV *krb5_free_kdc_req) (krb5_context, krb5_kdc_req * ); void (*krb5int_set_prompt_types) (krb5_context, krb5_prompt_type *); krb5_error_code (*encode_krb5_authdata_elt) (const krb5_authdata *rep, krb5_data **code); } krb5int_access; #define KRB5INT_ACCESS_VERSION \ (((krb5_int32)((sizeof(krb5int_access) & 0xFFFF) | \ (KRB5INT_ACCESS_STRUCT_VERSION << 16))) & 0xFFFFFFFF) krb5_error_code KRB5_CALLCONV krb5int_accessor (krb5int_access*, krb5_int32); /* Ick -- some krb524 and krb4 support placed in the krb5 library, because AFS (and potentially other applications?) use the krb4 object as an opaque token, which (in some implementations) is not in fact a krb4 ticket, so we don't want to drag in the krb4 support just to enable this. */ #define KRB524_SERVICE "krb524" #define KRB524_PORT 4444 /* v4lifetime.c */ extern krb5_int32 krb5int_krb_life_to_time(krb5_int32, int); extern int krb5int_krb_time_to_life(krb5_int32, krb5_int32); /* conv_creds.c */ int krb5int_encode_v4tkt (struct ktext *v4tkt, char *buf, unsigned int *encoded_len); /* send524.c */ int krb5int_524_sendto_kdc (krb5_context context, const krb5_data * message, const krb5_data * realm, krb5_data * reply, struct sockaddr *, socklen_t *); /* temporary -- this should be under lib/krb5/ccache somewhere */ struct _krb5_ccache { krb5_magic magic; const struct _krb5_cc_ops *ops; krb5_pointer data; }; /* * Per-type ccache cursor. */ struct krb5_cc_ptcursor { const struct _krb5_cc_ops *ops; krb5_pointer data; }; typedef struct krb5_cc_ptcursor *krb5_cc_ptcursor; struct _krb5_cc_ops { krb5_magic magic; char *prefix; const char * (KRB5_CALLCONV *get_name) (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *resolve) (krb5_context, krb5_ccache *, const char *); krb5_error_code (KRB5_CALLCONV *gen_new) (krb5_context, krb5_ccache *); krb5_error_code (KRB5_CALLCONV *init) (krb5_context, krb5_ccache, krb5_principal); krb5_error_code (KRB5_CALLCONV *destroy) (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *close) (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *store) (krb5_context, krb5_ccache, krb5_creds *); krb5_error_code (KRB5_CALLCONV *retrieve) (krb5_context, krb5_ccache, krb5_flags, krb5_creds *, krb5_creds *); krb5_error_code (KRB5_CALLCONV *get_princ) (krb5_context, krb5_ccache, krb5_principal *); krb5_error_code (KRB5_CALLCONV *get_first) (krb5_context, krb5_ccache, krb5_cc_cursor *); krb5_error_code (KRB5_CALLCONV *get_next) (krb5_context, krb5_ccache, krb5_cc_cursor *, krb5_creds *); krb5_error_code (KRB5_CALLCONV *end_get) (krb5_context, krb5_ccache, krb5_cc_cursor *); krb5_error_code (KRB5_CALLCONV *remove_cred) (krb5_context, krb5_ccache, krb5_flags, krb5_creds *); krb5_error_code (KRB5_CALLCONV *set_flags) (krb5_context, krb5_ccache, krb5_flags); krb5_error_code (KRB5_CALLCONV *get_flags) (krb5_context, krb5_ccache, krb5_flags *); krb5_error_code (KRB5_CALLCONV *ptcursor_new)(krb5_context, krb5_cc_ptcursor *); krb5_error_code (KRB5_CALLCONV *ptcursor_next)(krb5_context, krb5_cc_ptcursor, krb5_ccache *); krb5_error_code (KRB5_CALLCONV *ptcursor_free)(krb5_context, krb5_cc_ptcursor *); krb5_error_code (KRB5_CALLCONV *move)(krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *lastchange)(krb5_context, krb5_ccache, krb5_timestamp *); krb5_error_code (KRB5_CALLCONV *wasdefault)(krb5_context, krb5_ccache, krb5_timestamp *); }; extern const krb5_cc_ops *krb5_cc_dfl_ops; krb5_error_code krb5int_cc_os_default_name(krb5_context context, char **name); /* * Cursor for iterating over ccache types */ struct krb5_cc_typecursor; typedef struct krb5_cc_typecursor *krb5_cc_typecursor; krb5_error_code krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *cursor); krb5_error_code krb5int_cc_typecursor_next( krb5_context context, krb5_cc_typecursor cursor, const struct _krb5_cc_ops **ops); krb5_error_code krb5int_cc_typecursor_free( krb5_context context, krb5_cc_typecursor *cursor); typedef struct _krb5_donot_replay { krb5_magic magic; krb5_ui_4 hash; char *server; /* null-terminated */ char *client; /* null-terminated */ char *msghash; /* null-terminated */ krb5_int32 cusec; krb5_timestamp ctime; } krb5_donot_replay; krb5_error_code krb5_rc_default (krb5_context, krb5_rcache *); krb5_error_code krb5_rc_resolve_type (krb5_context, krb5_rcache *,char *); krb5_error_code krb5_rc_resolve_full (krb5_context, krb5_rcache *,char *); char * krb5_rc_get_type (krb5_context, krb5_rcache); char * krb5_rc_default_type (krb5_context); char * krb5_rc_default_name (krb5_context); krb5_error_code krb5_auth_to_rep (krb5_context, krb5_tkt_authent *, krb5_donot_replay *); krb5_error_code KRB5_CALLCONV krb5_rc_initialize (krb5_context, krb5_rcache,krb5_deltat); krb5_error_code KRB5_CALLCONV krb5_rc_recover_or_initialize (krb5_context, krb5_rcache,krb5_deltat); krb5_error_code KRB5_CALLCONV krb5_rc_recover (krb5_context, krb5_rcache); krb5_error_code KRB5_CALLCONV krb5_rc_destroy (krb5_context, krb5_rcache); krb5_error_code KRB5_CALLCONV krb5_rc_close (krb5_context, krb5_rcache); krb5_error_code KRB5_CALLCONV krb5_rc_store (krb5_context, krb5_rcache,krb5_donot_replay *); krb5_error_code KRB5_CALLCONV krb5_rc_expunge (krb5_context, krb5_rcache); krb5_error_code KRB5_CALLCONV krb5_rc_get_lifespan (krb5_context, krb5_rcache,krb5_deltat *); char *KRB5_CALLCONV krb5_rc_get_name (krb5_context, krb5_rcache); krb5_error_code KRB5_CALLCONV krb5_rc_resolve (krb5_context, krb5_rcache, char *); typedef struct _krb5_kt_ops { krb5_magic magic; char *prefix; /* routines always present */ krb5_error_code (KRB5_CALLCONV *resolve) (krb5_context, const char *, krb5_keytab *); krb5_error_code (KRB5_CALLCONV *get_name) (krb5_context, krb5_keytab, char *, unsigned int); krb5_error_code (KRB5_CALLCONV *close) (krb5_context, krb5_keytab); krb5_error_code (KRB5_CALLCONV *get) (krb5_context, krb5_keytab, krb5_const_principal, krb5_kvno, krb5_enctype, krb5_keytab_entry *); krb5_error_code (KRB5_CALLCONV *start_seq_get) (krb5_context, krb5_keytab, krb5_kt_cursor *); krb5_error_code (KRB5_CALLCONV *get_next) (krb5_context, krb5_keytab, krb5_keytab_entry *, krb5_kt_cursor *); krb5_error_code (KRB5_CALLCONV *end_get) (krb5_context, krb5_keytab, krb5_kt_cursor *); /* routines to be included on extended version (write routines) */ krb5_error_code (KRB5_CALLCONV *add) (krb5_context, krb5_keytab, krb5_keytab_entry *); krb5_error_code (KRB5_CALLCONV *remove) (krb5_context, krb5_keytab, krb5_keytab_entry *); /* Handle for serializer */ const krb5_ser_entry *serializer; } krb5_kt_ops; extern const krb5_kt_ops krb5_kt_dfl_ops; extern krb5_error_code krb5int_translate_gai_error (int); /* Not sure it's ready for exposure just yet. */ extern krb5_error_code krb5int_c_mandatory_cksumtype (krb5_context, krb5_enctype, krb5_cksumtype *); extern int krb5int_crypto_init (void); extern int krb5int_prng_init(void); /* * SUNW14resync * Hack (?) to neuter C99 "inline" which causes warnings w/our build. */ #define inline /* Some data comparison and conversion functions. */ #if 0 static inline int data_cmp(krb5_data d1, krb5_data d2) { if (d1.length < d2.length) return -1; if (d1.length > d2.length) return 1; return memcmp(d1.data, d2.data, d1.length); } static inline int data_eq (krb5_data d1, krb5_data d2) { return data_cmp(d1, d2) == 0; } #else static inline int data_eq (krb5_data d1, krb5_data d2) { return (d1.length == d2.length && !memcmp(d1.data, d2.data, d1.length)); } #endif static inline krb5_data string2data (char *str) { krb5_data d; d.magic = KV5M_DATA; d.length = strlen(str); d.data = str; return d; } /*LINTED*/ static inline int data_eq_string (krb5_data d, char *s) { return data_eq(d, string2data(s)); } /*LINTED*/ static inline int authdata_eq (krb5_authdata a1, krb5_authdata a2) { return (a1.ad_type == a2.ad_type && a1.length == a2.length && !memcmp(a1.contents, a2.contents, a1.length)); } /* Solaris kerberos */ krb5_boolean KRB5_CALLCONV is_in_keytype (krb5_const krb5_enctype *keytype, int numkeytypes, krb5_enctype enctype); /* * Solaris Kerberos * Use krb5_getuid() to select the mechanism to obtain the uid. */ extern uid_t krb5_getuid(); /* * Referral definitions, debugging hooks, and subfunctions. */ #define KRB5_REFERRAL_MAXHOPS 5 /* #define DEBUG_REFERRALS */ #ifdef DEBUG_REFERRALS void krb5int_dbgref_dump_principal(char *, krb5_principal); #endif /* Common hostname-parsing code. */ krb5_error_code KRB5_CALLCONV krb5int_clean_hostname (krb5_context, const char *, char *, size_t); /* * Solaris Kerberos * Kernel & user space realloc. */ void *krb5int_realloc (void *oldp, size_t new_size, size_t old_size); #endif /* _KRB5_INT_H */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ static unsigned short load_16_be (unsigned char *p) { return (p[1] | (p[0] << 8)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ static unsigned int load_32_be (unsigned char *p) { return (p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ #include static UINT64_TYPE load_64_be (unsigned char *p) { return ((UINT64_TYPE)load_32_be(p) << 32) | load_32_be(p+4); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ static void store_16_be (unsigned int val, unsigned char *p) { p[0] = (val >> 8) & 0xff; p[1] = (val ) & 0xff; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ static void store_32_be (unsigned int val, unsigned char *p) { p[0] = (val >> 24) & 0xff; p[1] = (val >> 16) & 0xff; p[2] = (val >> 8) & 0xff; p[3] = (val ) & 0xff; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ static void store_64_be (UINT64_TYPE val, unsigned char *p) { p[0] = (unsigned char)((val >> 56) & 0xff); p[1] = (unsigned char)((val >> 48) & 0xff); p[2] = (unsigned char)((val >> 40) & 0xff); p[3] = (unsigned char)((val >> 32) & 0xff); p[4] = (unsigned char)((val >> 24) & 0xff); p[5] = (unsigned char)((val >> 16) & 0xff); p[6] = (unsigned char)((val >> 8) & 0xff); p[7] = (unsigned char)((val ) & 0xff); } /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * k5-platform.h * * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * Some platform-dependent definitions to sync up the C support level. * Some to a C99-ish level, some related utility code. * * Currently: * + make "static inline" work * + 64-bit types and load/store code * + SIZE_MAX * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces */ #ifndef K5_PLATFORM_H #define K5_PLATFORM_H /* Solaris Kerberos */ #ifndef _KERNEL #include #include "autoconf.h" /* Initialization and finalization function support for libraries. At top level, before the functions are defined or even declared: MAKE_INIT_FUNCTION(init_fn); MAKE_FINI_FUNCTION(fini_fn); Then: int init_fn(void) { ... } void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... } In code, in the same file: err = CALL_INIT_FUNCTION(init_fn); To trigger or verify the initializer invocation from another file, a helper function must be created. This model handles both the load-time execution (Windows) and delayed execution (pthread_once) approaches, and should be able to guarantee in both cases that the init function is run once, in one thread, before other stuff in the library is done; furthermore, the finalization code should only run if the initialization code did. (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via another function hidden in macros, but this is hairy enough already.) The init_fn and fini_fn names should be chosen such that any exported names staring with those names, and optionally followed by additional characters, fits in with any namespace constraints on the library in question. There's also PROGRAM_EXITING() currently always defined as zero. If there's some trivial way to find out if the fini function is being called because the program that the library is linked into is exiting, we can just skip all the work because the resources are about to be freed up anyways. Generally this is likely to be the same as distinguishing whether the library was loaded dynamically while the program was running, or loaded as part of program startup. On most platforms, I don't think we can distinguish these cases easily, and it's probably not worth expending any significant effort. (Note in particular that atexit() won't do, because if the library is explicitly loaded and unloaded, it would have to be able to deregister the atexit callback function. Also, the system limit on atexit callbacks may be small.) Implementation outline: Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that is sought at library build time, and code is added to invoke the function when the library is unloaded. MAKE_INIT_FUNCTION does likewise, but the function is invoked when the library is loaded, and an extra variable is declared to hold an error code and a "yes the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag isn't set, otherwise returns the error code. UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a name derived from the function name, containing a k5_once_t (pthread_once_t or int), an error code, and a pointer to the function. The function itself is declared static, but the associated variable has external linkage. CALL_INIT_FUNCTION ensures thath the function is called exactly once (pthread_once or just check the flag) and returns the stored error code (or the pthread_once error). (That's the basic idea. With some debugging assert() calls and such, it's a bit more complicated. And we also need to handle doing the pthread test at run time on systems where that works, so we use the k5_once_t stuff instead.) UNIX, with compiler support: MAKE_FINI_FUNCTION declares the function as a destructor, and the run time linker support or whatever will cause it to be invoked when the library is unloaded, the program ends, etc. UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with a magic name that is sought at library build time, and linker options are used to mark it as a finalization function for the library. The symbol must be exported. UNIX, no library finalization support: The finalization function never runs, and we leak memory. Tough. DELAY_INITIALIZER will be defined by the configure script if we want to use k5_once instead of load-time initialization. That'll be the preferred method on most systems except Windows, where we have to initialize some mutexes. For maximum flexibility in defining the macros, the function name parameter should be a simple name, not even a macro defined as another name. The function should have a unique name, and should conform to whatever namespace is used by the library in question. (We do have export lists, but (1) they're not used for all platforms, and (2) they're not used for static libraries.) If the macro expansion needs the function to have been declared, it must include a declaration. If it is not necessary for the symbol name to be exported from the object file, the macro should declare it as "static". Hence the signature must exactly match "void foo(void)". (ANSI C allows a static declaration followed by a non-static one; the result is internal linkage.) The macro expansion has to come before the function, because gcc apparently won't act on "__attribute__((constructor))" if it comes after the function definition. This is going to be compiler- and environment-specific, and may require some support at library build time, and/or "asm" statements. But through macro expansion and auxiliary functions, we should be able to handle most things except #pragma. It's okay for this code to require that the library be built with the same compiler and compiler options throughout, but we shouldn't require that the library and application use the same compiler. For static libraries, we don't really care about cleanup too much, since it's all memory handling and mutex allocation which will all be cleaned up when the program exits. Thus, it's okay if gcc-built static libraries don't play nicely with cc-built executables when it comes to static constructors, just as long as it doesn't cause linking to fail. For dynamic libraries on UNIX, we'll use pthread_once-type support to do delayed initialization, so if finalization can't be made to work, we'll only have memory leaks in a load/use/unload cycle. If anyone (like, say, the OS vendor) complains about this, they can tell us how to get a shared library finalization function invoked automatically. Currently there's --disable-delayed-initialization for preventing the initialization from being delayed on UNIX, but that's mainly just for testing the linker options for initialization, and will probably be removed at some point. */ /* Helper macros. */ # define JOIN__2_2(A,B) A ## _ ## _ ## B # define JOIN__2(A,B) JOIN__2_2(A,B) /* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set, always provide a function by the expected name, even if we're delaying initialization. */ #if defined(DELAY_INITIALIZER) /* Run the initialization code during program execution, at the latest possible moment. This means multiple threads may be active. */ # include "k5-thread.h" typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t; # ifdef USE_LINKER_INIT_OPTION # define MAYBE_DUMMY_INIT(NAME) \ void JOIN__2(NAME, auxinit) () { } # else # define MAYBE_DUMMY_INIT(NAME) # endif # ifdef __GNUC__ /* Do it in macro form so we get the file/line of the invocation if the assertion fails. */ # define k5_call_init_function(I) \ (__extension__ ({ \ k5_init_t *k5int_i = (I); \ int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \ (k5int_err \ ? k5int_err \ : (assert(k5int_i->did_run != 0), k5int_i->error)); \ })) # define MAYBE_DEFINE_CALLINIT_FUNCTION # else # define MAYBE_DEFINE_CALLINIT_FUNCTION \ static int k5_call_init_function(k5_init_t *i) \ { \ int err; \ err = k5_once(&i->once, i->fn); \ if (err) \ return err; \ assert (i->did_run != 0); \ return i->error; \ } # endif # define MAKE_INIT_FUNCTION(NAME) \ static int NAME(void); \ MAYBE_DUMMY_INIT(NAME) \ /* forward declaration for use in initializer */ \ static void JOIN__2(NAME, aux) (void); \ static k5_init_t JOIN__2(NAME, once) = \ { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \ MAYBE_DEFINE_CALLINIT_FUNCTION \ static void JOIN__2(NAME, aux) (void) \ { \ JOIN__2(NAME, once).did_run = 1; \ JOIN__2(NAME, once).error = NAME(); \ } \ /* so ';' following macro use won't get error */ \ static int NAME(void) # define CALL_INIT_FUNCTION(NAME) \ k5_call_init_function(& JOIN__2(NAME, once)) /* This should be called in finalization only, so we shouldn't have multiple active threads mucking around in our library at this point. So ignore the once_t object and just look at the flag. XXX Could we have problems with memory coherence between processors if we don't invoke mutex/once routines? Probably not, the application code should already be coordinating things such that the library code is not in use by this point, and memory synchronization will be needed there. */ # define INITIALIZER_RAN(NAME) \ (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0) # define PROGRAM_EXITING() (0) #elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS) /* Run initializer at load time, via GCC/C++ hook magic. */ # ifdef USE_LINKER_INIT_OPTION /* Both gcc and linker option?? Favor gcc. */ # define MAYBE_DUMMY_INIT(NAME) \ void JOIN__2(NAME, auxinit) () { } # else # define MAYBE_DUMMY_INIT(NAME) # endif typedef struct { int error; unsigned char did_run; } k5_init_t; # define MAKE_INIT_FUNCTION(NAME) \ MAYBE_DUMMY_INIT(NAME) \ static k5_init_t JOIN__2(NAME, ran) \ = { 0, 2 }; \ static void JOIN__2(NAME, aux)(void) \ __attribute__((constructor)); \ static int NAME(void); \ static void JOIN__2(NAME, aux)(void) \ { \ JOIN__2(NAME, ran).error = NAME(); \ JOIN__2(NAME, ran).did_run = 3; \ } \ static int NAME(void) # define CALL_INIT_FUNCTION(NAME) \ (JOIN__2(NAME, ran).did_run == 3 \ ? JOIN__2(NAME, ran).error \ : (abort(),0)) # define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0) # define PROGRAM_EXITING() (0) #elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32) /* Run initializer at load time, via linker magic, or in the case of WIN32, win_glue.c hard-coded knowledge. */ typedef struct { int error; unsigned char did_run; } k5_init_t; # define MAKE_INIT_FUNCTION(NAME) \ static k5_init_t JOIN__2(NAME, ran) \ = { 0, 2 }; \ static int NAME(void); \ void JOIN__2(NAME, auxinit)() \ { \ JOIN__2(NAME, ran).error = NAME(); \ JOIN__2(NAME, ran).did_run = 3; \ } \ static int NAME(void) # define CALL_INIT_FUNCTION(NAME) \ (JOIN__2(NAME, ran).did_run == 3 \ ? JOIN__2(NAME, ran).error \ : (abort(),0)) # define INITIALIZER_RAN(NAME) \ (JOIN__2(NAME, ran).error == 0) # define PROGRAM_EXITING() (0) #else # error "Don't know how to do load-time initializers for this configuration." # define PROGRAM_EXITING() (0) #endif #if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32) /* If we're told the linker option will be used, it doesn't really matter what compiler we're using. Do it the same way regardless. */ # ifdef __hpux /* On HP-UX, we need this auxiliary function. At dynamic load or unload time (but *not* program startup and termination for link-time specified libraries), the linker-indicated function is called with a handle on the library and a flag indicating whether it's being loaded or unloaded. The "real" fini function doesn't need to be exported, so declare it static. As usual, the final declaration is just for syntactic convenience, so the top-level invocation of this macro can be followed by a semicolon. */ # include # define MAKE_FINI_FUNCTION(NAME) \ static void NAME(void); \ void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \ void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \ static void NAME(void) # else /* not hpux */ # define MAKE_FINI_FUNCTION(NAME) \ void NAME(void) # endif #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS) /* If we're using gcc, if the C++ support works, the compiler should build executables and shared libraries that support the use of static constructors and destructors. The C compiler supports a function attribute that makes use of the same facility as C++. XXX How do we know if the C++ support actually works? */ # define MAKE_FINI_FUNCTION(NAME) \ static void NAME(void) __attribute__((destructor)) #elif !defined(SHARED) /* In this case, we just don't care about finalization. The code will still define the function, but we won't do anything with it. Annoying: This may generate unused-function warnings. */ # define MAKE_FINI_FUNCTION(NAME) \ static void NAME(void) #else # error "Don't know how to do unload-time finalization for this configuration." #endif #endif /* !_KERNEL */ /* 64-bit support: krb5_ui_8 and krb5_int64. This should move to krb5.h eventually, but without the namespace pollution from the autoconf macros. */ #if defined(HAVE_STDINT_H) || defined(HAVE_INTTYPES_H) # ifdef HAVE_STDINT_H # include # endif # ifdef HAVE_INTTYPES_H # include # endif # define INT64_TYPE int64_t # define UINT64_TYPE uint64_t #elif defined(_WIN32) # define INT64_TYPE signed __int64 # define UINT64_TYPE unsigned __int64 #else /* not Windows, and neither stdint.h nor inttypes.h */ # define INT64_TYPE signed long long # define UINT64_TYPE unsigned long long #endif #ifndef _KERNEL #include #endif /* !_KERNEL */ #ifndef SIZE_MAX # define SIZE_MAX ((size_t)((size_t)0 - 1)) #endif /* Read and write integer values as (unaligned) octet strings in specific byte orders. Add per-platform optimizations later if needed. (E.g., maybe x86 unaligned word stores and gcc/asm instructions for byte swaps, etc.) */ /* Solaris Kerberos: To avoid problems with lint the following functions can be found in separate header files. */ #if 0 static void store_16_be (unsigned int val, unsigned char *p) { p[0] = (val >> 8) & 0xff; p[1] = (val ) & 0xff; } static void store_16_le (unsigned int val, unsigned char *p) { p[1] = (val >> 8) & 0xff; p[0] = (val ) & 0xff; } static void store_32_be (unsigned int val, unsigned char *p) { p[0] = (val >> 24) & 0xff; p[1] = (val >> 16) & 0xff; p[2] = (val >> 8) & 0xff; p[3] = (val ) & 0xff; } static void store_32_le (unsigned int val, unsigned char *p) { p[3] = (val >> 24) & 0xff; p[2] = (val >> 16) & 0xff; p[1] = (val >> 8) & 0xff; p[0] = (val ) & 0xff; } static void store_64_be (UINT64_TYPE val, unsigned char *p) { p[0] = (unsigned char)((val >> 56) & 0xff); p[1] = (unsigned char)((val >> 48) & 0xff); p[2] = (unsigned char)((val >> 40) & 0xff); p[3] = (unsigned char)((val >> 32) & 0xff); p[4] = (unsigned char)((val >> 24) & 0xff); p[5] = (unsigned char)((val >> 16) & 0xff); p[6] = (unsigned char)((val >> 8) & 0xff); p[7] = (unsigned char)((val ) & 0xff); } static void store_64_le (UINT64_TYPE val, unsigned char *p) { p[7] = (unsigned char)((val >> 56) & 0xff); p[6] = (unsigned char)((val >> 48) & 0xff); p[5] = (unsigned char)((val >> 40) & 0xff); p[4] = (unsigned char)((val >> 32) & 0xff); p[3] = (unsigned char)((val >> 24) & 0xff); p[2] = (unsigned char)((val >> 16) & 0xff); p[1] = (unsigned char)((val >> 8) & 0xff); p[0] = (unsigned char)((val ) & 0xff); } static unsigned short load_16_be (unsigned char *p) { return (p[1] | (p[0] << 8)); } static unsigned short load_16_le (unsigned char *p) { return (p[0] | (p[1] << 8)); } static unsigned int load_32_be (unsigned char *p) { return (p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24)); } static unsigned int load_32_le (unsigned char *p) { return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); } static UINT64_TYPE load_64_be (unsigned char *p) { return ((UINT64_TYPE)load_32_be(p) << 32) | load_32_be(p+4); } static UINT64_TYPE load_64_le (unsigned char *p) { return ((UINT64_TYPE)load_32_le(p+4) << 32) | load_32_le(p); } #endif /* Make the interfaces to getpwnam and getpwuid consistent. Model the wrappers on the POSIX thread-safe versions, but use the unsafe system versions if the safe ones don't exist or we can't figure out their interfaces. */ /* SUNW15resync - just have Solaris relevant ones */ #define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) #define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) /* Return true if the snprintf return value RESULT reflects a buffer overflow for the buffer size SIZE. We cast the result to unsigned int for two reasons. First, old implementations of snprintf (such as the one in Solaris 9 and prior) return -1 on a buffer overflow. Casting the result to -1 will convert that value to UINT_MAX, which should compare larger than any reasonable buffer size. Second, comparing signed and unsigned integers will generate warnings with some compilers, and can have unpredictable results, particularly when the relative widths of the types is not known (size_t may be the same width as int or larger). */ #define SNPRINTF_OVERFLOW(result, size) \ ((unsigned int)(result) >= (size_t)(size)) #endif /* K5_PLATFORM_H */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * include/k5-thread.h * * Copyright 2004,2005,2006 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. * * * Preliminary thread support. */ #ifndef K5_THREAD_H #define K5_THREAD_H #ifdef _KERNEL #include typedef kmutex_t k5_mutex_t; #define K5_MUTEX_PARTIAL_INITIALIZER {0} /* ARGSUSED */ static void k5_mutex_assert_locked(k5_mutex_t *m) { } static int k5_mutex_lock(k5_mutex_t *m) { mutex_enter(m); return (0); } static int k5_mutex_unlock(k5_mutex_t *m) { mutex_exit(m); return(0); } #else /* _KERNEL */ #include "autoconf.h" #ifndef KRB5_CALLCONV # define KRB5_CALLCONV #endif #ifndef KRB5_CALLCONV_C # define KRB5_CALLCONV_C #endif /* Interface (tentative): Mutex support: // Between these two, we should be able to do pure compile-time // and pure run-time initialization. // POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER, // finish does nothing // Windows: partial initializer is an invalid handle, // finish does the real initialization work // debug: partial initializer sets one magic value, // finish verifies and sets a new magic value for // lock/unlock to check k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER; int k5_mutex_finish_init(k5_mutex_t *); // for dynamic allocation int k5_mutex_init(k5_mutex_t *); // Must work for both kinds of alloc, even if it means adding flags. int k5_mutex_destroy(k5_mutex_t *); // As before. int k5_mutex_lock(k5_mutex_t *); int k5_mutex_unlock(k5_mutex_t *); In each library, one new function to finish the static mutex init, and any other library-wide initialization that might be desired. On POSIX, this function would be called via the second support function (see below). On Windows, it would be called at library load time. These functions, or functions they calls, should be the only places that k5_mutex_finish_init gets called. A second function or macro called at various possible "first" entry points which either calls pthread_once on the first function (POSIX), or checks some flag set by the first function (Windows, debug support), and possibly returns an error. (In the non-threaded case, a simple flag can be used to avoid multiple invocations, and the mutexes don't need run-time initialization anyways.) A third function for library termination calls mutex_destroy on each mutex for the library. This function would be called automatically at library unload time. If it turns out to be needed at exit time for libraries that don't get unloaded, perhaps we should also use atexit(). Any static mutexes should be cleaned up with k5_mutex_destroy here. How does that second support function invoke the first support function only once? Through something modelled on pthread_once that I haven't written up yet. Probably: k5_once_t foo_once = K5_ONCE_INIT; k5_once(k5_once_t *, void (*)(void)); For POSIX: Map onto pthread_once facility. For non-threaded case: A simple flag. For Windows: Not needed; library init code takes care of it. XXX: A general k5_once mechanism isn't possible for Windows, without faking it through named mutexes or mutexes initialized at startup. I was only using it in one place outside these headers, so I'm dropping the general scheme. Eventually the existing uses in k5-thread.h and k5-platform.h will be converted to pthread_once or static variables. Thread-specific data: // TSD keys are limited in number in gssapi/krb5/com_err; enumerate // them all. This allows support code init to allocate the // necessary storage for pointers all at once, and avoids any // possible error in key creation. enum { ... } k5_key_t; // Register destructor function. Called in library init code. int k5_key_register(k5_key_t, void (*destructor)(void *)); // Returns NULL or data. void *k5_getspecific(k5_key_t); // Returns error if key out of bounds, or the pointer table can't // be allocated. A call to k5_key_register must have happened first. // This may trigger the calling of pthread_setspecific on POSIX. int k5_setspecific(k5_key_t, void *); // Called in library termination code. // Trashes data in all threads, calling the registered destructor // (but calling it from the current thread). int k5_key_delete(k5_key_t); For the non-threaded version, the support code will have a static array indexed by k5_key_t values, and get/setspecific simply access the array elements. The TSD destructor table is global state, protected by a mutex if threads are enabled. Debug support: Not much. Might check if k5_key_register has been called and abort if not. Any actual external symbols will use the krb5int_ prefix. The k5_ names will be simple macros or inline functions to rename the external symbols, or slightly more complex ones to expand the implementation inline (e.g., map to POSIX versions and/or debug code using __FILE__ and the like). More to be added, perhaps. */ #undef DEBUG_THREADS /* SUNW14resync XXX */ #undef DEBUG_THREADS_LOC /* SUNW14resync XXX */ #undef DEBUG_THREADS_SLOW /* debugging stuff that'll slow things down? */ #undef DEBUG_THREADS_STATS #ifndef _KERNEL #include #include #define ASSERT assert #endif /* For tracking locations, of (e.g.) last lock or unlock of mutex. */ #ifdef DEBUG_THREADS_LOC typedef struct { const char *filename; int lineno; } k5_debug_loc; #define K5_DEBUG_LOC_INIT { __FILE__, __LINE__ } #if __GNUC__ >= 2 #define K5_DEBUG_LOC (__extension__ (k5_debug_loc)K5_DEBUG_LOC_INIT) #else static inline k5_debug_loc k5_debug_make_loc(const char *file, int line) { k5_debug_loc l; l.filename = file; l.lineno = line; return l; } #define K5_DEBUG_LOC (k5_debug_make_loc(__FILE__,__LINE__)) #endif #else /* ! DEBUG_THREADS_LOC */ typedef char k5_debug_loc; #define K5_DEBUG_LOC_INIT 0 #define K5_DEBUG_LOC 0 #endif #define k5_debug_update_loc(L) ((L) = K5_DEBUG_LOC) /* Statistics gathering: Currently incomplete, don't try enabling it. Eventually: Report number of times locked, total and standard deviation of the time the lock was held, total and std dev time spent waiting for the lock. "Report" will probably mean "write a line to a file if a magic environment variable is set." */ #ifdef DEBUG_THREADS_STATS #if HAVE_TIME_H && (!defined(HAVE_SYS_TIME_H) || defined(TIME_WITH_SYS_TIME)) # include #endif #if HAVE_SYS_TIME_H # include #endif #ifdef HAVE_STDINT_H # include #endif /* for memset */ #include /* for uint64_t */ #include typedef uint64_t k5_debug_timediff_t; /* or long double */ typedef struct timeval k5_debug_time_t; static inline k5_debug_timediff_t timediff(k5_debug_time_t t2, k5_debug_time_t t1) { return (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec); } static inline k5_debug_time_t get_current_time(void) { struct timeval tv; if (gettimeofday(&tv,0) < 0) { tv.tv_sec = tv.tv_usec = 0; } return tv; } struct k5_timediff_stats { k5_debug_timediff_t valmin, valmax, valsum, valsqsum; }; typedef struct { int count; k5_debug_time_t time_acquired, time_created; struct k5_timediff_stats lockwait, lockheld; } k5_debug_mutex_stats; #define k5_mutex_init_stats(S) \ (memset((S), 0, sizeof(k5_debug_mutex_stats)), \ (S)->time_created = get_current_time(), \ 0) #define k5_mutex_finish_init_stats(S) (0) #define K5_MUTEX_STATS_INIT { 0, {0}, {0}, {0}, {0} } typedef k5_debug_time_t k5_mutex_stats_tmp; #define k5_mutex_stats_start() get_current_time() void KRB5_CALLCONV krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m, k5_mutex_stats_tmp start); void KRB5_CALLCONV krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m); #define k5_mutex_lock_update_stats krb5int_mutex_lock_update_stats #define k5_mutex_unlock_update_stats krb5int_mutex_unlock_update_stats void KRB5_CALLCONV krb5int_mutex_report_stats(/* k5_mutex_t *m */); #else typedef char k5_debug_mutex_stats; #define k5_mutex_init_stats(S) (*(S) = 's', 0) #define k5_mutex_finish_init_stats(S) (0) #define K5_MUTEX_STATS_INIT 's' typedef int k5_mutex_stats_tmp; #define k5_mutex_stats_start() (0) #ifdef __GNUC__ static void k5_mutex_lock_update_stats(k5_debug_mutex_stats *m, k5_mutex_stats_tmp t) { } #else # define k5_mutex_lock_update_stats(M,S) (S) #endif #define k5_mutex_unlock_update_stats(M) (*(M) = 's') /* If statistics tracking isn't enabled, these functions don't actually do anything. Declare anyways so we can do type checking etc. */ void KRB5_CALLCONV krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m, k5_mutex_stats_tmp start); void KRB5_CALLCONV krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m); void KRB5_CALLCONV krb5int_mutex_report_stats(/* k5_mutex_t *m */); #define krb5int_mutex_report_stats(M) ((M)->stats = 'd') #endif /* Define the OS mutex bit. */ /* First, if we're not actually doing multiple threads, do we want the debug support or not? */ #ifdef DEBUG_THREADS enum k5_mutex_init_states { K5_MUTEX_DEBUG_PARTLY_INITIALIZED = 0x12, K5_MUTEX_DEBUG_INITIALIZED, K5_MUTEX_DEBUG_DESTROYED }; enum k5_mutex_flag_states { K5_MUTEX_DEBUG_UNLOCKED = 0x23, K5_MUTEX_DEBUG_LOCKED }; typedef struct { enum k5_mutex_init_states initialized; enum k5_mutex_flag_states locked; } k5_os_nothread_mutex; # define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER \ { K5_MUTEX_DEBUG_PARTLY_INITIALIZED, K5_MUTEX_DEBUG_UNLOCKED } # define k5_os_nothread_mutex_finish_init(M) \ (ASSERT((M)->initialized != K5_MUTEX_DEBUG_INITIALIZED), \ ASSERT((M)->initialized == K5_MUTEX_DEBUG_PARTLY_INITIALIZED), \ ASSERT((M)->locked == K5_MUTEX_DEBUG_UNLOCKED), \ (M)->initialized = K5_MUTEX_DEBUG_INITIALIZED, 0) # define k5_os_nothread_mutex_init(M) \ ((M)->initialized = K5_MUTEX_DEBUG_INITIALIZED, \ (M)->locked = K5_MUTEX_DEBUG_UNLOCKED, 0) # define k5_os_nothread_mutex_destroy(M) \ (ASSERT((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED), \ (M)->initialized = K5_MUTEX_DEBUG_DESTROYED, 0) # define k5_os_nothread_mutex_lock(M) \ (k5_os_nothread_mutex_assert_unlocked(M), \ (M)->locked = K5_MUTEX_DEBUG_LOCKED, 0) # define k5_os_nothread_mutex_unlock(M) \ (k5_os_nothread_mutex_assert_locked(M), \ (M)->locked = K5_MUTEX_DEBUG_UNLOCKED, 0) # define k5_os_nothread_mutex_assert_locked(M) \ (ASSERT((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED), \ ASSERT((M)->locked != K5_MUTEX_DEBUG_UNLOCKED), \ ASSERT((M)->locked == K5_MUTEX_DEBUG_LOCKED)) # define k5_os_nothread_mutex_assert_unlocked(M) \ (ASSERT((M)->initialized == K5_MUTEX_DEBUG_INITIALIZED), \ ASSERT((M)->locked != K5_MUTEX_DEBUG_LOCKED), \ ASSERT((M)->locked == K5_MUTEX_DEBUG_UNLOCKED)) #else /* threads disabled and not debugging */ typedef char k5_os_nothread_mutex; # define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER 0 /* Empty inline functions avoid the "statement with no effect" warnings, and do better type-checking than functions that don't use their arguments. */ /* SUNW 1.4resync, remove "inline" to avoid warning */ /* ARGSUSED */ /* LINTED */ static int k5_os_nothread_mutex_finish_init(k5_os_nothread_mutex *m) { return 0; } /* ARGSUSED */ /* LINTED */ static int k5_os_nothread_mutex_init(k5_os_nothread_mutex *m) { return 0; } /* ARGSUSED */ /* LINTED */ static int k5_os_nothread_mutex_destroy(k5_os_nothread_mutex *m) { return 0; } /* ARGSUSED */ /* LINTED */ static int k5_os_nothread_mutex_lock(k5_os_nothread_mutex *m) { return 0; } /* ARGSUSED */ /* LINTED */ static int k5_os_nothread_mutex_unlock(k5_os_nothread_mutex *m) { return 0; } # define k5_os_nothread_mutex_assert_locked(M) ((void)0) # define k5_os_nothread_mutex_assert_unlocked(M) ((void)0) #endif /* Values: 2 - function has not been run 3 - function has been run 4 - function is being run -- deadlock detected */ typedef unsigned char k5_os_nothread_once_t; # define K5_OS_NOTHREAD_ONCE_INIT 2 # define k5_os_nothread_once(O,F) \ (*(O) == 3 ? 0 \ : *(O) == 2 ? (*(O) = 4, (F)(), *(O) = 3, 0) \ : (ASSERT(*(O) != 4), ASSERT(*(O) == 2 || *(O) == 3), 0)) #ifndef ENABLE_THREADS typedef k5_os_nothread_mutex k5_os_mutex; # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER # define k5_os_mutex_finish_init k5_os_nothread_mutex_finish_init # define k5_os_mutex_init k5_os_nothread_mutex_init # define k5_os_mutex_destroy k5_os_nothread_mutex_destroy # define k5_os_mutex_lock k5_os_nothread_mutex_lock # define k5_os_mutex_unlock k5_os_nothread_mutex_unlock # define k5_os_mutex_assert_locked k5_os_nothread_mutex_assert_locked # define k5_os_mutex_assert_unlocked k5_os_nothread_mutex_assert_unlocked # define k5_once_t k5_os_nothread_once_t # define K5_ONCE_INIT K5_OS_NOTHREAD_ONCE_INIT # define k5_once k5_os_nothread_once #elif HAVE_PTHREAD # include /* Weak reference support, etc. Linux: Stub mutex routines exist, but pthread_once does not. Solaris: In libc there's a pthread_once that doesn't seem to do anything. Bleah. But pthread_mutexattr_setrobust_np is defined only in libpthread. However, some version of GNU libc (Red Hat's Fedora Core 5, reportedly) seems to have that function, but no declaration, so we'd have to declare it in order to test for its address. We now have tests to see if pthread_once actually works, so stick with that for now. IRIX 6.5 stub pthread support in libc is really annoying. The pthread_mutex_lock function returns ENOSYS for a program not linked against -lpthread. No link-time failure, no weak symbols, etc. The C library doesn't provide pthread_once; we can use weak reference support for that. If weak references are not available, then for now, we assume that the pthread support routines will always be available -- either the real thing, or functional stubs that merely prohibit creating threads. If we find a platform with non-functional stubs and no weak references, we may have to resort to some hack like dlsym on the symbol tables of the current process. */ #ifdef HAVE_PRAGMA_WEAK_REF # pragma weak pthread_once # pragma weak pthread_mutex_lock # pragma weak pthread_mutex_unlock # pragma weak pthread_mutex_destroy # pragma weak pthread_mutex_init # pragma weak pthread_self # pragma weak pthread_equal # ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP_IN_THREAD_LIB # pragma weak pthread_mutexattr_setrobust_np # endif # if !defined HAVE_PTHREAD_ONCE # define K5_PTHREADS_LOADED (&pthread_once != 0) # elif !defined HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP \ && defined HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP_IN_THREAD_LIB # define K5_PTHREADS_LOADED (&pthread_mutexattr_setrobust_np != 0) # else # define K5_PTHREADS_LOADED (1) # endif #else /* no pragma weak support */ # define K5_PTHREADS_LOADED (1) #endif #if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__)) /* IRIX 6.5 stub pthread support in libc is really annoying. The pthread_mutex_lock function returns ENOSYS for a program not linked against -lpthread. No link-time failure, no weak reference tests, etc. The C library doesn't provide pthread_once; we can use weak reference support for that. */ # ifndef HAVE_PRAGMA_WEAK_REF # if defined(__GNUC__) && __GNUC__ < 3 # error "Please update to a newer gcc with weak symbol support, or switch to native cc, reconfigure and recompile." # else # error "Weak reference support is required" # endif # endif # define USE_PTHREAD_LOCK_ONLY_IF_LOADED #endif #if !defined(HAVE_PTHREAD_MUTEX_LOCK) && !defined(USE_PTHREAD_LOCK_ONLY_IF_LOADED) # define USE_PTHREAD_LOCK_ONLY_IF_LOADED #endif #ifdef HAVE_PRAGMA_WEAK_REF /* Can't rely on useful stubs -- see above regarding Solaris. */ typedef struct { pthread_once_t o; k5_os_nothread_once_t n; } k5_once_t; # define K5_ONCE_INIT { PTHREAD_ONCE_INIT, K5_OS_NOTHREAD_ONCE_INIT } # define k5_once(O,F) (K5_PTHREADS_LOADED \ ? pthread_once(&(O)->o,F) \ : k5_os_nothread_once(&(O)->n,F)) #else typedef pthread_once_t k5_once_t; # define K5_ONCE_INIT PTHREAD_ONCE_INIT # define k5_once pthread_once #endif typedef struct { pthread_mutex_t p; #ifdef DEBUG_THREADS pthread_t owner; #endif #ifdef USE_PTHREAD_LOCK_ONLY_IF_LOADED k5_os_nothread_mutex n; #endif } k5_os_mutex; #ifdef DEBUG_THREADS # ifdef __GNUC__ # define k5_pthread_mutex_lock(M) \ ({ \ k5_os_mutex *_m2 = (M); \ int _r2 = pthread_mutex_lock(&_m2->p); \ if (_r2 == 0) _m2->owner = pthread_self(); \ _r2; \ }) # else static int k5_pthread_mutex_lock(k5_os_mutex *m) { int r = pthread_mutex_lock(&m->p); if (r) return r; m->owner = pthread_self(); return 0; } # endif # define k5_pthread_assert_locked(M) \ (K5_PTHREADS_LOADED \ ? ASSERT(pthread_equal((M)->owner, pthread_self())) \ : (void)0) # define k5_pthread_mutex_unlock(M) \ (k5_pthread_assert_locked(M), \ (M)->owner = (pthread_t) 0, \ pthread_mutex_unlock(&(M)->p)) #else # define k5_pthread_mutex_lock(M) pthread_mutex_lock(&(M)->p) /* LINTED */ static void k5_pthread_assert_locked(k5_os_mutex *m) { } # define k5_pthread_mutex_unlock(M) pthread_mutex_unlock(&(M)->p) #endif /* Define as functions to: (1) eliminate "statement with no effect" warnings for "0" (2) encourage type-checking in calling code */ /* LINTED */ static void k5_pthread_assert_unlocked(pthread_mutex_t *m) { } #if defined(DEBUG_THREADS_SLOW) && HAVE_SCHED_H && (HAVE_SCHED_YIELD || HAVE_PRAGMA_WEAK_REF) # include # if !HAVE_SCHED_YIELD # pragma weak sched_yield # define MAYBE_SCHED_YIELD() ((void)((&sched_yield != NULL) ? sched_yield() : 0)) # else # define MAYBE_SCHED_YIELD() ((void)sched_yield()) # endif #else # define MAYBE_SCHED_YIELD() ((void)0) #endif /* It may not be obvious why this function is desirable. I want to call pthread_mutex_lock, then sched_yield, then look at the return code from pthread_mutex_lock. That can't be implemented in a macro without a temporary variable, or GNU C extensions. There used to be an inline function which did it, with both functions called from the inline function. But that messes with the debug information on a lot of configurations, and you can't tell where the inline function was called from. (Typically, gdb gives you the name of the function from which the inline function was called, and a line number within the inline function itself.) With this auxiliary function, pthread_mutex_lock can be called at the invoking site via a macro; once it returns, the inline function is called (with messed-up line-number info for gdb hopefully localized to just that call). */ #ifdef __GNUC__ #define return_after_yield(R) \ __extension__ ({ \ int _r = (R); \ MAYBE_SCHED_YIELD(); \ _r; \ }) #else static int return_after_yield(int r) { MAYBE_SCHED_YIELD(); return r; } #endif #ifdef USE_PTHREAD_LOCK_ONLY_IF_LOADED # if defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) && defined(DEBUG_THREADS) # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, (pthread_t) 0, \ K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER } # elif defined(DEBUG_THREADS) # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, \ K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER } # else # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_MUTEX_INITIALIZER, K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER } # endif asdfsdf # define k5_os_mutex_finish_init(M) \ k5_os_nothread_mutex_finish_init(&(M)->n) # define k5_os_mutex_init(M) \ (k5_os_nothread_mutex_init(&(M)->n), \ (K5_PTHREADS_LOADED \ ? pthread_mutex_init(&(M)->p, 0) \ : 0)) # define k5_os_mutex_destroy(M) \ (k5_os_nothread_mutex_destroy(&(M)->n), \ (K5_PTHREADS_LOADED \ ? pthread_mutex_destroy(&(M)->p) \ : 0)) # define k5_os_mutex_lock(M) \ return_after_yield(K5_PTHREADS_LOADED \ ? k5_pthread_mutex_lock(M) \ : k5_os_nothread_mutex_lock(&(M)->n)) # define k5_os_mutex_unlock(M) \ (MAYBE_SCHED_YIELD(), \ (K5_PTHREADS_LOADED \ ? k5_pthread_mutex_unlock(M) \ : k5_os_nothread_mutex_unlock(&(M)->n))) # define k5_os_mutex_assert_unlocked(M) \ (K5_PTHREADS_LOADED \ ? k5_pthread_assert_unlocked(&(M)->p) \ : k5_os_nothread_mutex_assert_unlocked(&(M)->n)) # define k5_os_mutex_assert_locked(M) \ (K5_PTHREADS_LOADED \ ? k5_pthread_assert_locked(M) \ : k5_os_nothread_mutex_assert_locked(&(M)->n)) #else # ifdef DEBUG_THREADS # ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, (pthread_t) 0 } # else # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0 } # endif # else # define K5_OS_MUTEX_PARTIAL_INITIALIZER \ { PTHREAD_MUTEX_INITIALIZER } # endif /* LINTED */ static int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; } # define k5_os_mutex_init(M) pthread_mutex_init(&(M)->p, 0) # define k5_os_mutex_destroy(M) pthread_mutex_destroy(&(M)->p) # define k5_os_mutex_lock(M) return_after_yield(k5_pthread_mutex_lock(M)) # define k5_os_mutex_unlock(M) (MAYBE_SCHED_YIELD(),k5_pthread_mutex_unlock(M)) # define k5_os_mutex_assert_unlocked(M) k5_pthread_assert_unlocked(&(M)->p) # define k5_os_mutex_assert_locked(M) k5_pthread_assert_locked(M) #endif /* is pthreads always available? */ #elif defined _WIN32 typedef struct { HANDLE h; int is_locked; } k5_os_mutex; # define K5_OS_MUTEX_PARTIAL_INITIALIZER { INVALID_HANDLE_VALUE, 0 } # define k5_os_mutex_finish_init(M) \ (ASSERT((M)->h == INVALID_HANDLE_VALUE), \ ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError()) # define k5_os_mutex_init(M) \ ((M)->is_locked = 0, \ ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError()) # define k5_os_mutex_destroy(M) \ (CloseHandle((M)->h) ? ((M)->h = 0, 0) : GetLastError()) static int k5_os_mutex_lock(k5_os_mutex *m) { DWORD res; res = WaitForSingleObject(m->h, INFINITE); if (res == WAIT_FAILED) return GetLastError(); /* Eventually these should be turned into some reasonable error code. */ ASSERT(res != WAIT_TIMEOUT); ASSERT(res != WAIT_ABANDONED); ASSERT(res == WAIT_OBJECT_0); /* Avoid locking twice. */ ASSERT(m->is_locked == 0); m->is_locked = 1; return 0; } # define k5_os_mutex_unlock(M) \ (ASSERT((M)->is_locked == 1), \ (M)->is_locked = 0, \ ReleaseMutex((M)->h) ? 0 : GetLastError()) # define k5_os_mutex_assert_unlocked(M) ((void)0) # define k5_os_mutex_assert_locked(M) ((void)0) #else # error "Thread support enabled, but thread system unknown" #endif typedef struct { k5_debug_loc loc_last, loc_created; k5_os_mutex os; k5_debug_mutex_stats stats; } k5_mutex_t; #define K5_MUTEX_PARTIAL_INITIALIZER \ { K5_DEBUG_LOC_INIT, K5_DEBUG_LOC_INIT, \ K5_OS_MUTEX_PARTIAL_INITIALIZER, K5_MUTEX_STATS_INIT } /* LINTED */ static int k5_mutex_init_1(k5_mutex_t *m, k5_debug_loc l) { int err = k5_os_mutex_init(&m->os); if (err) return err; m->loc_created = m->loc_last = l; err = k5_mutex_init_stats(&m->stats); ASSERT(err == 0); return 0; } #define k5_mutex_init(M) k5_mutex_init_1((M), K5_DEBUG_LOC) /* LINTED */ static int k5_mutex_finish_init_1(k5_mutex_t *m, k5_debug_loc l) { int err = k5_os_mutex_finish_init(&m->os); if (err) return err; m->loc_created = m->loc_last = l; err = k5_mutex_finish_init_stats(&m->stats); ASSERT(err == 0); return 0; } #define k5_mutex_finish_init(M) k5_mutex_finish_init_1((M), K5_DEBUG_LOC) #define k5_mutex_destroy(M) \ (k5_os_mutex_assert_unlocked(&(M)->os), \ k5_mutex_lock(M), (M)->loc_last = K5_DEBUG_LOC, k5_mutex_unlock(M), \ k5_os_mutex_destroy(&(M)->os)) #ifdef __GNUC__ #define k5_mutex_lock(M) \ __extension__ ({ \ int _err = 0; \ k5_mutex_t *_m = (M); \ _err = k5_os_mutex_lock(&_m->os); \ if (_err == 0) _m->loc_last = K5_DEBUG_LOC; \ _err; \ }) #else /* LINTED */ static int k5_mutex_lock_1(k5_mutex_t *m, k5_debug_loc l) { int err = 0; err = k5_os_mutex_lock(&m->os); if (err) return err; m->loc_last = l; return err; } #define k5_mutex_lock(M) k5_mutex_lock_1(M, K5_DEBUG_LOC) #endif #define k5_mutex_unlock(M) \ (k5_mutex_assert_locked(M), \ (M)->loc_last = K5_DEBUG_LOC, \ k5_os_mutex_unlock(&(M)->os)) #define k5_mutex_assert_locked(M) k5_os_mutex_assert_locked(&(M)->os) #define k5_mutex_assert_unlocked(M) k5_os_mutex_assert_unlocked(&(M)->os) #define k5_assert_locked k5_mutex_assert_locked #define k5_assert_unlocked k5_mutex_assert_unlocked /* Thread-specific data; implemented in a support file, because we'll need to keep track of some global data for cleanup purposes. Note that the callback function type is such that the C library routine free() is a valid callback. */ typedef enum { K5_KEY_COM_ERR, K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, K5_KEY_GSS_KRB5_CCACHE_NAME, K5_KEY_GSS_KRB5_ERROR_MESSAGE, K5_KEY_GSS_SPNEGO_ERROR_MESSAGE, K5_KEY_MAX } k5_key_t; /* rename shorthand symbols for export */ #define k5_key_register krb5int_key_register #define k5_getspecific krb5int_getspecific #define k5_setspecific krb5int_setspecific #define k5_key_delete krb5int_key_delete extern int k5_key_register(k5_key_t, void (*)(void *)); extern void *k5_getspecific(k5_key_t); extern int k5_setspecific(k5_key_t, void *); extern int k5_key_delete(k5_key_t); extern int KRB5_CALLCONV krb5int_mutex_alloc (k5_mutex_t **); extern void KRB5_CALLCONV krb5int_mutex_free (k5_mutex_t *); extern int KRB5_CALLCONV krb5int_mutex_lock (k5_mutex_t *); extern int KRB5_CALLCONV krb5int_mutex_unlock (k5_mutex_t *); /* In time, many of the definitions above should move into the support library, and this file should be greatly simplified. For type definitions, that'll take some work, since other data structures incorporate mutexes directly, and our mutex type is dependent on configuration options and system attributes. For most functions, though, it should be relatively easy. For now, plugins should use the exported functions, and not the above macros, and use krb5int_mutex_alloc for allocations. */ #ifdef PLUGIN #undef k5_mutex_lock #define k5_mutex_lock krb5int_mutex_lock #undef k5_mutex_unlock #define k5_mutex_unlock krb5int_mutex_unlock #endif #endif /* _KERNEL */ #endif /* multiple inclusion? */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" extern const struct krb5_keyhash_provider krb5int_keyhash_descbc; extern const struct krb5_keyhash_provider krb5int_keyhash_md5des; extern const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5; /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* This is the prologue to krb5.h */ /* Unfortunately some of these defines are compiler dependent */ #ifndef _KRB5_H #define _KRB5_H #define SIZEOF_INT 4 #ifdef _LP64 #define SIZEOF_LONG 8 #else #define SIZEOF_LONG 4 #endif #define SIZEOF_SHORT 2 #define HAVE_STDARG_H 1 #define HAVE_SYS_TYPES_H 1 /* End of prologue section */ /* * include/krb5.h * * Copyright 1989,1990,1995,2001, 2003 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. * * * General definitions for Kerberos version 5. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef KRB5_GENERAL__ #define KRB5_GENERAL__ #ifdef _KERNEL #include #include #include #include /* * Just to be safe lets make sure the buffers are zero'ed after * malloc() as some code assumes this is the case. To avoid warnings * of duplicated defines let remove the old one if present. */ #ifdef MALLOC #undef MALLOC #endif #define MALLOC(n) kmem_zalloc((n), KM_SLEEP) #define FREE(x, n) kmem_free((x), (n)) #define CALLOC(n, s) kmem_zalloc((n)*(s), KM_SLEEP) #define strcpy(dst,src,n) bcopy((src),(dst),(n)) #define mutex_lock(lck) mutex_enter(lck) #define mutex_unlock(lck) mutex_exit(lck) #else /* !_KERNEL */ #define MALLOC(n) malloc(n) #define FREE(x, n) free(x) #define CALLOC(n, s) calloc((n), (s)) #include #include #include #include #include /* for *_MAX */ #endif /* _KERNEL */ /* By default, do not expose deprecated interfaces. */ /* SUNW14resync - we need to enable this for rlogind and such */ #ifndef KRB5_DEPRECATED #define KRB5_DEPRECATED 1 #endif /* Do not expose private interfaces. Build system will override. */ /* SUNW14resync - for the Solaris build we set it to 1 here */ #ifndef KRB5_PRIVATE #define KRB5_PRIVATE 1 #endif #if defined(__MACH__) && defined(__APPLE__) # include # if TARGET_RT_MAC_CFM # error "Use KfM 4.0 SDK headers for CFM compilation." # endif #endif #if defined(_MSDOS) || defined(_WIN32) #include #endif #ifndef KRB5_CONFIG__ #ifndef KRB5_CALLCONV #define KRB5_CALLCONV #define KRB5_CALLCONV_C #endif /* !KRB5_CALLCONV */ #endif /* !KRB5_CONFIG__ */ #ifndef KRB5_CALLCONV_WRONG #define KRB5_CALLCONV_WRONG #endif /* SUNW14resync XXX */ #include #include #ifndef THREEPARAMOPEN #define THREEPARAMOPEN(x,y,z) open(x,y,z) #endif /* * Solaris Kerberos: * Samba needs a couple of these interfaces so old crypto is enabled. */ #define KRB5_OLD_CRYPTO #ifndef KRB5INT_BEGIN_DECLS #if defined(__cplusplus) #define KRB5INT_BEGIN_DECLS extern "C" { #define KRB5INT_END_DECLS } #else #define KRB5INT_BEGIN_DECLS #define KRB5INT_END_DECLS #endif #endif KRB5INT_BEGIN_DECLS #if TARGET_OS_MAC # pragma options align=mac68k #endif /* from profile.h */ struct _profile_t; /* typedef struct _profile_t *profile_t; */ /* * begin wordsize.h */ /* * Word-size related definition. */ typedef unsigned char krb5_octet; #if INT_MAX == 0x7fff typedef int krb5_int16; typedef unsigned int krb5_ui_2; #elif SHRT_MAX == 0x7fff typedef short krb5_int16; typedef unsigned short krb5_ui_2; #else #error undefined 16 bit type #endif #if INT_MAX == 0x7fffffffL typedef int krb5_int32; typedef unsigned int krb5_ui_4; #elif LONG_MAX == 0x7fffffffL typedef long krb5_int32; typedef unsigned long krb5_ui_4; #elif SHRT_MAX == 0x7fffffffL typedef short krb5_int32; typedef unsigned short krb5_ui_4; #else #error: undefined 32 bit type #endif #define VALID_INT_BITS INT_MAX #define VALID_UINT_BITS UINT_MAX #define KRB5_INT32_MAX 2147483647 /* this strange form is necessary since - is a unary operator, not a sign indicator */ #define KRB5_INT32_MIN (-KRB5_INT32_MAX-1) #define KRB5_INT16_MAX 65535 /* this strange form is necessary since - is a unary operator, not a sign indicator */ #define KRB5_INT16_MIN (-KRB5_INT16_MAX-1) /* * end wordsize.h */ /* * begin "base-defs.h" */ /* * Basic definitions for Kerberos V5 library */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif typedef unsigned int krb5_boolean; typedef unsigned int krb5_msgtype; typedef unsigned int krb5_kvno; typedef krb5_int32 krb5_addrtype; typedef krb5_int32 krb5_enctype; typedef krb5_int32 krb5_cksumtype; typedef krb5_int32 krb5_authdatatype; typedef krb5_int32 krb5_keyusage; typedef krb5_int32 krb5_preauthtype; /* This may change, later on */ typedef krb5_int32 krb5_flags; typedef krb5_int32 krb5_timestamp; typedef krb5_int32 krb5_error_code; typedef krb5_int32 krb5_deltat; typedef krb5_error_code krb5_magic; typedef struct _krb5_data { krb5_magic magic; unsigned int length; char *data; } krb5_data; typedef struct _krb5_octet_data { krb5_magic magic; unsigned int length; krb5_octet *data; } krb5_octet_data; /* * Hack length for crypto library to use the afs_string_to_key It is * equivalent to -1 without possible sign extension * We also overload for an unset salt type length - which is also -1, but * hey, why not.... */ #define SALT_TYPE_AFS_LENGTH UINT_MAX #define SALT_TYPE_NO_LENGTH UINT_MAX typedef void * krb5_pointer; typedef void const * krb5_const_pointer; typedef struct krb5_principal_data { krb5_magic magic; krb5_data realm; krb5_data *data; /* An array of strings */ krb5_int32 length; krb5_int32 type; } krb5_principal_data; typedef krb5_principal_data * krb5_principal; /* * Per V5 spec on definition of principal types */ /* Name type not known */ #define KRB5_NT_UNKNOWN 0 /* Just the name of the principal as in DCE, or for users */ #define KRB5_NT_PRINCIPAL 1 /* Service and other unique instance (krbtgt) */ #define KRB5_NT_SRV_INST 2 /* Service with host name as instance (telnet, rcommands) */ #define KRB5_NT_SRV_HST 3 /* Service with host as remaining components */ #define KRB5_NT_SRV_XHST 4 /* Unique ID */ #define KRB5_NT_UID 5 /* PKINIT */ #define KRB5_NT_X500_PRINCIPAL 6 /* Name in form of SMTP email name */ #define KRB5_NT_SMTP_NAME 7 /* Windows 2000 UPN */ #define KRB5_NT_ENTERPRISE_PRINCIPAL 10 /* Windows 2000 UPN and SID */ #define KRB5_NT_MS_PRINCIPAL -128 /* NT 4 style name */ #define KRB5_NT_MS_PRINCIPAL_AND_ID -129 /* NT 4 style name and SID */ #define KRB5_NT_ENT_PRINCIPAL_AND_ID -130 /* constant version thereof: */ typedef const krb5_principal_data *krb5_const_principal; #define krb5_princ_realm(context, princ) (&(princ)->realm) #define krb5_princ_set_realm(context, princ,value) ((princ)->realm = *(value)) #define krb5_princ_set_realm_length(context, princ,value) (princ)->realm.length = (value) #define krb5_princ_set_realm_data(context, princ,value) (princ)->realm.data = (value) #define krb5_princ_size(context, princ) (princ)->length #define krb5_princ_type(context, princ) (princ)->type #define krb5_princ_name(context, princ) (princ)->data #define krb5_princ_component(context, princ,i) \ (((i) < krb5_princ_size(context, princ)) \ ? (princ)->data + (i) \ : NULL) /* * Constants for realm referrals. */ #define KRB5_REFERRAL_REALM "" /* * Referral-specific functions. */ krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *); /* * end "base-defs.h" */ /* * begin "hostaddr.h" */ /* structure for address */ typedef struct _krb5_address { krb5_magic magic; krb5_addrtype addrtype; unsigned int length; krb5_octet *contents; } krb5_address; /* per Kerberos v5 protocol spec */ #define ADDRTYPE_INET 0x0002 #define ADDRTYPE_CHAOS 0x0005 #define ADDRTYPE_XNS 0x0006 #define ADDRTYPE_ISO 0x0007 #define ADDRTYPE_DDP 0x0010 #define ADDRTYPE_INET6 0x0018 /* not yet in the spec... */ #define ADDRTYPE_ADDRPORT 0x0100 #define ADDRTYPE_IPPORT 0x0101 /* macros to determine if a type is a local type */ #define ADDRTYPE_IS_LOCAL(addrtype) (addrtype & 0x8000) /* * end "hostaddr.h" */ struct _krb5_context; typedef struct _krb5_context * krb5_context; struct _krb5_auth_context; typedef struct _krb5_auth_context * krb5_auth_context; struct _krb5_cryptosystem_entry; /* SUNW EF (I assume) crypto mods ... */ struct _krb5_keyblock; /* * keyblocks will contain a list of derived keys, * this structure will contain the derived key data. */ typedef struct _dk_node { krb5_keyusage usage; struct _krb5_keyblock *derived_key; uchar_t dkid; /* derived key identifier byte */ struct _dk_node *next; } krb5_dk_node; /* * begin "encryption.h" */ typedef struct _krb5_keyblock { krb5_magic magic; krb5_enctype enctype; unsigned int length; krb5_octet *contents; krb5_dk_node *dk_list; /* list of keys derived from this key */ #ifdef _KERNEL crypto_mech_type_t kef_mt; crypto_key_t kef_key; crypto_ctx_template_t key_tmpl; #else CK_OBJECT_HANDLE hKey; /* PKCS#11 key object handle */ pid_t pid; /* fork safety */ #endif /* _KERNEL */ } krb5_keyblock; typedef struct _krb5_checksum { krb5_magic magic; krb5_cksumtype checksum_type; /* checksum type */ unsigned int length; krb5_octet *contents; } krb5_checksum; typedef struct _krb5_encrypt_block { krb5_magic magic; krb5_enctype crypto_entry; /* to call krb5_encrypt_size, you need this. it was a pointer, but it doesn't have to be. gross. */ krb5_keyblock *key; } krb5_encrypt_block; typedef struct _krb5_enc_data { krb5_magic magic; krb5_enctype enctype; krb5_kvno kvno; krb5_data ciphertext; } krb5_enc_data; /* per Kerberos v5 protocol spec */ #define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ #define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */ #define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */ #define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */ /* XXX deprecated? */ #define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */ #define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */ #define ENCTYPE_DES_HMAC_SHA1 0x0008 #define ENCTYPE_DES3_CBC_SHA1 0x0010 #define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011 #define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012 #define ENCTYPE_ARCFOUR_HMAC 0x0017 #define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018 #define ENCTYPE_UNKNOWN 0x01ff #define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 #define CKSUMTYPE_DESCBC 0x0004 /* des-mac-k */ /* rsa-md4-des-k */ #define CKSUMTYPE_RSA_MD5 0x0007 #define CKSUMTYPE_RSA_MD5_DES 0x0008 #define CKSUMTYPE_NIST_SHA 0x0009 #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 #define CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /*Microsoft md5 hmac cksumtype*/ /* The following are entropy source designations. Whenever * krb5_C_random_add_entropy is called, one of these source ids is passed * in. This allows the library to better estimate bits of * entropy in the sample and to keep track of what sources of entropy have * contributed enough entropy. Sources marked internal MUST NOT be * used by applications outside the Kerberos library */ enum { KRB5_C_RANDSOURCE_OLDAPI = 0, /*calls to krb5_C_RANDOM_SEED (INTERNAL)*/ KRB5_C_RANDSOURCE_OSRAND = 1, /* /dev/random or equivalent (internal)*/ KRB5_C_RANDSOURCE_TRUSTEDPARTY = 2, /* From KDC or other trusted party*/ /*This source should be used carefully; data in this category * should be from a third party trusted to give random bits * For example keys issued by the KDC in the application server. */ KRB5_C_RANDSOURCE_TIMING = 3, /* Timing of operations*/ KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL = 4, /*Protocol data possibly from attacker*/ KRB5_C_RANDSOURCE_MAX = 5 /*Do not use; maximum source ID*/ }; #ifndef krb5_roundup /* round x up to nearest multiple of y */ #define krb5_roundup(x, y) ((((x) + (y) - 1)/(y))*(y)) #endif /* roundup */ /* macro function definitions to help clean up code */ #ifndef _KERNEL #define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) #define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) #else #define krb5_x(ptr,args) ((*(ptr)) args) #define krb5_xc(ptr,args) ((*(ptr)) args) #endif krb5_error_code KRB5_CALLCONV krb5_c_encrypt (krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_data *input, krb5_enc_data *output); krb5_error_code KRB5_CALLCONV krb5_c_decrypt (krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_enc_data *input, krb5_data *output); krb5_error_code KRB5_CALLCONV krb5_c_encrypt_length (krb5_context context, krb5_enctype enctype, size_t inputlen, size_t *length); krb5_error_code KRB5_CALLCONV krb5_c_block_size (krb5_context context, krb5_enctype enctype, size_t *blocksize); krb5_error_code KRB5_CALLCONV krb5_c_keylengths (krb5_context context, krb5_enctype enctype, size_t *keybytes, size_t *keylength); krb5_error_code KRB5_CALLCONV krb5_c_init_state(krb5_context, const krb5_keyblock *, krb5_keyusage, krb5_data *); krb5_error_code KRB5_CALLCONV krb5_c_free_state(krb5_context, const krb5_keyblock *, krb5_data *); krb5_error_code KRB5_CALLCONV krb5_c_make_random_key (krb5_context context, krb5_enctype enctype, krb5_keyblock *random_key); krb5_error_code KRB5_CALLCONV krb5_c_random_to_key (krb5_context context, krb5_enctype enctype, krb5_data *random_data, krb5_keyblock *k5_random_key); /* Register a new entropy sample with the PRNG. may cause * the PRNG to be reseeded, although this is not guaranteed. See previous randsource definitions * for information on how each source should be used. */ krb5_error_code KRB5_CALLCONV krb5_c_random_add_entropy (krb5_context context, unsigned int randsource_id, const krb5_data *data); krb5_error_code KRB5_CALLCONV krb5_c_random_make_octets (krb5_context context, krb5_data *data); /* * Collect entropy from the OS if possible. strong requests that as strong * of a source of entropy as available be used. Setting strong may * increase the probability of blocking and should not be used for normal * applications. Good uses include seeding the PRNG for kadmind * and realm setup. * If successful is non-null, then successful is set to 1 if the OS provided * entropy else zero. */ #if 0 /* SUNW14resync - not used in Solaris */ krb5_error_code KRB5_CALLCONV krb5_c_random_os_entropy (krb5_context context, int strong, int *success); #endif /*deprecated*/ krb5_error_code KRB5_CALLCONV krb5_c_random_seed (krb5_context context, krb5_data *data); krb5_error_code KRB5_CALLCONV krb5_c_string_to_key (krb5_context context, krb5_enctype enctype, const krb5_data *string, const krb5_data *salt, krb5_keyblock *key); krb5_error_code KRB5_CALLCONV krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, const krb5_data *string, const krb5_data *salt, const krb5_data *params, krb5_keyblock *key); krb5_error_code KRB5_CALLCONV krb5_c_enctype_compare (krb5_context context, krb5_enctype e1, krb5_enctype e2, krb5_boolean *similar); krb5_error_code KRB5_CALLCONV krb5_c_make_checksum (krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum); krb5_error_code KRB5_CALLCONV krb5_c_verify_checksum (krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid); krb5_error_code KRB5_CALLCONV krb5_c_checksum_length (krb5_context context, krb5_cksumtype cksumtype, size_t *length); krb5_error_code KRB5_CALLCONV krb5_c_keyed_checksum_types (krb5_context context, krb5_enctype enctype, unsigned int *count, krb5_cksumtype **cksumtypes); #define KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS 1 #define KRB5_KEYUSAGE_KDC_REP_TICKET 2 #define KRB5_KEYUSAGE_AS_REP_ENCPART 3 #define KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY 4 #define KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY 5 #define KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM 6 #define KRB5_KEYUSAGE_TGS_REQ_AUTH 7 #define KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY 8 #define KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY 9 #define KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM 10 #define KRB5_KEYUSAGE_AP_REQ_AUTH 11 #define KRB5_KEYUSAGE_AP_REP_ENCPART 12 #define KRB5_KEYUSAGE_KRB_PRIV_ENCPART 13 #define KRB5_KEYUSAGE_KRB_CRED_ENCPART 14 #define KRB5_KEYUSAGE_KRB_SAFE_CKSUM 15 #define KRB5_KEYUSAGE_APP_DATA_ENCRYPT 16 #define KRB5_KEYUSAGE_APP_DATA_CKSUM 17 #define KRB5_KEYUSAGE_KRB_ERROR_CKSUM 18 #define KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM 19 #define KRB5_KEYUSAGE_AD_MTE 20 #define KRB5_KEYUSAGE_AD_ITE 21 /* XXX need to register these */ #define KRB5_KEYUSAGE_GSS_TOK_MIC 22 #define KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG 23 #define KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV 24 /* Defined in hardware preauth draft */ #define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM 25 #define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID 26 #define KRB5_KEYUSAGE_PA_SAM_RESPONSE 27 /* Defined in KDC referrals draft */ #define KRB5_KEYUSAGE_PA_REFERRAL 26 /* XXX note conflict with above */ krb5_boolean KRB5_CALLCONV krb5_c_valid_enctype (krb5_enctype ktype); krb5_boolean KRB5_CALLCONV krb5_c_valid_cksumtype (krb5_cksumtype ctype); krb5_boolean KRB5_CALLCONV krb5_c_is_coll_proof_cksum (krb5_cksumtype ctype); krb5_boolean KRB5_CALLCONV krb5_c_is_keyed_cksum (krb5_cksumtype ctype); #if KRB5_PRIVATE /* Use the above four instead. */ krb5_boolean KRB5_CALLCONV valid_enctype (krb5_enctype ktype); krb5_boolean KRB5_CALLCONV valid_cksumtype (krb5_cksumtype ctype); krb5_boolean KRB5_CALLCONV is_coll_proof_cksum (krb5_cksumtype ctype); krb5_boolean KRB5_CALLCONV is_keyed_cksum (krb5_cksumtype ctype); #endif #ifdef KRB5_OLD_CRYPTO /* * old cryptosystem routine prototypes. These are now layered * on top of the functions above. */ krb5_error_code KRB5_CALLCONV krb5_encrypt (krb5_context context, krb5_const_pointer inptr, krb5_pointer outptr, size_t size, krb5_encrypt_block * eblock, krb5_pointer ivec); krb5_error_code KRB5_CALLCONV krb5_decrypt (krb5_context context, krb5_const_pointer inptr, krb5_pointer outptr, size_t size, krb5_encrypt_block * eblock, krb5_pointer ivec); krb5_error_code KRB5_CALLCONV krb5_process_key (krb5_context context, krb5_encrypt_block * eblock, const krb5_keyblock * key); krb5_error_code KRB5_CALLCONV krb5_finish_key (krb5_context context, krb5_encrypt_block * eblock); krb5_error_code KRB5_CALLCONV krb5_string_to_key (krb5_context context, const krb5_encrypt_block * eblock, krb5_keyblock * keyblock, const krb5_data * data, const krb5_data * salt); krb5_error_code KRB5_CALLCONV krb5_init_random_key (krb5_context context, const krb5_encrypt_block * eblock, const krb5_keyblock * keyblock, krb5_pointer * ptr); krb5_error_code KRB5_CALLCONV krb5_finish_random_key (krb5_context context, const krb5_encrypt_block * eblock, krb5_pointer * ptr); krb5_error_code KRB5_CALLCONV krb5_random_key (krb5_context context, const krb5_encrypt_block * eblock, krb5_pointer ptr, krb5_keyblock ** keyblock); krb5_enctype KRB5_CALLCONV krb5_eblock_enctype (krb5_context context, const krb5_encrypt_block * eblock); krb5_error_code KRB5_CALLCONV krb5_use_enctype (krb5_context context, krb5_encrypt_block * eblock, krb5_enctype enctype); size_t KRB5_CALLCONV krb5_encrypt_size (size_t length, krb5_enctype crypto); size_t KRB5_CALLCONV krb5_checksum_size (krb5_context context, krb5_cksumtype ctype); krb5_error_code KRB5_CALLCONV krb5_calculate_checksum (krb5_context context, krb5_cksumtype ctype, krb5_const_pointer in, size_t in_length, krb5_const_pointer seed, size_t seed_length, krb5_checksum * outcksum); krb5_error_code KRB5_CALLCONV krb5_verify_checksum (krb5_context context, krb5_cksumtype ctype, const krb5_checksum * cksum, krb5_const_pointer in, size_t in_length, krb5_const_pointer seed, size_t seed_length); #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_random_confounder (size_t, krb5_pointer); krb5_error_code krb5_encrypt_data (krb5_context context, krb5_keyblock *key, krb5_pointer ivec, krb5_data *data, krb5_enc_data *enc_data); krb5_error_code krb5_decrypt_data (krb5_context context, krb5_keyblock *key, krb5_pointer ivec, krb5_enc_data *data, krb5_data *enc_data); #endif #endif /* KRB5_OLD_CRYPTO */ /* * end "encryption.h" */ /* * begin "fieldbits.h" */ /* kdc_options for kdc_request */ /* options is 32 bits; each host is responsible to put the 4 bytes representing these bits into net order before transmission */ /* #define KDC_OPT_RESERVED 0x80000000 */ #define KDC_OPT_FORWARDABLE 0x40000000 #define KDC_OPT_FORWARDED 0x20000000 #define KDC_OPT_PROXIABLE 0x10000000 #define KDC_OPT_PROXY 0x08000000 #define KDC_OPT_ALLOW_POSTDATE 0x04000000 #define KDC_OPT_POSTDATED 0x02000000 /* #define KDC_OPT_UNUSED 0x01000000 */ #define KDC_OPT_RENEWABLE 0x00800000 /* #define KDC_OPT_UNUSED 0x00400000 */ /* #define KDC_OPT_RESERVED 0x00200000 */ /* #define KDC_OPT_RESERVED 0x00100000 */ /* #define KDC_OPT_RESERVED 0x00080000 */ /* #define KDC_OPT_RESERVED 0x00040000 */ #define KDC_OPT_REQUEST_ANONYMOUS 0x00020000 #define KDC_OPT_CANONICALIZE 0x00010000 /* #define KDC_OPT_RESERVED 0x00008000 */ /* #define KDC_OPT_RESERVED 0x00004000 */ /* #define KDC_OPT_RESERVED 0x00002000 */ /* #define KDC_OPT_RESERVED 0x00001000 */ /* #define KDC_OPT_RESERVED 0x00000800 */ /* #define KDC_OPT_RESERVED 0x00000400 */ /* #define KDC_OPT_RESERVED 0x00000200 */ /* #define KDC_OPT_RESERVED 0x00000100 */ /* #define KDC_OPT_RESERVED 0x00000080 */ /* #define KDC_OPT_RESERVED 0x00000040 */ #define KDC_OPT_DISABLE_TRANSITED_CHECK 0x00000020 #define KDC_OPT_RENEWABLE_OK 0x00000010 #define KDC_OPT_ENC_TKT_IN_SKEY 0x00000008 /* #define KDC_OPT_UNUSED 0x00000004 */ #define KDC_OPT_RENEW 0x00000002 #define KDC_OPT_VALIDATE 0x00000001 /* * Mask of ticket flags in the TGT which should be converted into KDC * options when using the TGT to get derivitive tickets. * * New mask = KDC_OPT_FORWARDABLE | KDC_OPT_PROXIABLE | * KDC_OPT_ALLOW_POSTDATE | KDC_OPT_RENEWABLE */ #define KDC_TKT_COMMON_MASK 0x54800000 /* definitions for ap_options fields */ /* ap_options are 32 bits; each host is responsible to put the 4 bytes representing these bits into net order before transmission */ #define AP_OPTS_RESERVED 0x80000000 #define AP_OPTS_USE_SESSION_KEY 0x40000000 #define AP_OPTS_MUTUAL_REQUIRED 0x20000000 /* #define AP_OPTS_RESERVED 0x10000000 */ /* #define AP_OPTS_RESERVED 0x08000000 */ /* #define AP_OPTS_RESERVED 0x04000000 */ /* #define AP_OPTS_RESERVED 0x02000000 */ /* #define AP_OPTS_RESERVED 0x01000000 */ /* #define AP_OPTS_RESERVED 0x00800000 */ /* #define AP_OPTS_RESERVED 0x00400000 */ /* #define AP_OPTS_RESERVED 0x00200000 */ /* #define AP_OPTS_RESERVED 0x00100000 */ /* #define AP_OPTS_RESERVED 0x00080000 */ /* #define AP_OPTS_RESERVED 0x00040000 */ /* #define AP_OPTS_RESERVED 0x00020000 */ /* #define AP_OPTS_RESERVED 0x00010000 */ /* #define AP_OPTS_RESERVED 0x00008000 */ /* #define AP_OPTS_RESERVED 0x00004000 */ /* #define AP_OPTS_RESERVED 0x00002000 */ /* #define AP_OPTS_RESERVED 0x00001000 */ /* #define AP_OPTS_RESERVED 0x00000800 */ /* #define AP_OPTS_RESERVED 0x00000400 */ /* #define AP_OPTS_RESERVED 0x00000200 */ /* #define AP_OPTS_RESERVED 0x00000100 */ /* #define AP_OPTS_RESERVED 0x00000080 */ /* #define AP_OPTS_RESERVED 0x00000040 */ /* #define AP_OPTS_RESERVED 0x00000020 */ /* #define AP_OPTS_RESERVED 0x00000010 */ /* #define AP_OPTS_RESERVED 0x00000008 */ /* #define AP_OPTS_RESERVED 0x00000004 */ /* #define AP_OPTS_RESERVED 0x00000002 */ #define AP_OPTS_USE_SUBKEY 0x00000001 #define AP_OPTS_WIRE_MASK 0xfffffff0 /* definitions for ad_type fields. */ #define AD_TYPE_RESERVED 0x8000 #define AD_TYPE_EXTERNAL 0x4000 #define AD_TYPE_REGISTERED 0x2000 #define AD_TYPE_FIELD_TYPE_MASK 0x1fff /* Ticket flags */ /* flags are 32 bits; each host is responsible to put the 4 bytes representing these bits into net order before transmission */ /* #define TKT_FLG_RESERVED 0x80000000 */ #define TKT_FLG_FORWARDABLE 0x40000000 #define TKT_FLG_FORWARDED 0x20000000 #define TKT_FLG_PROXIABLE 0x10000000 #define TKT_FLG_PROXY 0x08000000 #define TKT_FLG_MAY_POSTDATE 0x04000000 #define TKT_FLG_POSTDATED 0x02000000 #define TKT_FLG_INVALID 0x01000000 #define TKT_FLG_RENEWABLE 0x00800000 #define TKT_FLG_INITIAL 0x00400000 #define TKT_FLG_PRE_AUTH 0x00200000 #define TKT_FLG_HW_AUTH 0x00100000 #define TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000 #define TKT_FLG_OK_AS_DELEGATE 0x00040000 #define TKT_FLG_ANONYMOUS 0x00020000 /* #define TKT_FLG_RESERVED 0x00010000 */ /* #define TKT_FLG_RESERVED 0x00008000 */ /* #define TKT_FLG_RESERVED 0x00004000 */ /* #define TKT_FLG_RESERVED 0x00002000 */ /* #define TKT_FLG_RESERVED 0x00001000 */ /* #define TKT_FLG_RESERVED 0x00000800 */ /* #define TKT_FLG_RESERVED 0x00000400 */ /* #define TKT_FLG_RESERVED 0x00000200 */ /* #define TKT_FLG_RESERVED 0x00000100 */ /* #define TKT_FLG_RESERVED 0x00000080 */ /* #define TKT_FLG_RESERVED 0x00000040 */ /* #define TKT_FLG_RESERVED 0x00000020 */ /* #define TKT_FLG_RESERVED 0x00000010 */ /* #define TKT_FLG_RESERVED 0x00000008 */ /* #define TKT_FLG_RESERVED 0x00000004 */ /* #define TKT_FLG_RESERVED 0x00000002 */ /* #define TKT_FLG_RESERVED 0x00000001 */ /* definitions for lr_type fields. */ #define LR_TYPE_THIS_SERVER_ONLY 0x8000 #define LR_TYPE_INTERPRETATION_MASK 0x7fff /* definitions for ad_type fields. */ #define AD_TYPE_EXTERNAL 0x4000 #define AD_TYPE_REGISTERED 0x2000 #define AD_TYPE_FIELD_TYPE_MASK 0x1fff #define AD_TYPE_INTERNAL_MASK 0x3fff /* definitions for msec direction bit for KRB_SAFE, KRB_PRIV */ #define MSEC_DIRBIT 0x8000 #define MSEC_VAL_MASK 0x7fff /* * end "fieldbits.h" */ /* * begin "proto.h" */ /* Protocol version number */ #define KRB5_PVNO 5 /* Message types */ #define KRB5_AS_REQ ((krb5_msgtype)10) /* Req for initial authentication */ #define KRB5_AS_REP ((krb5_msgtype)11) /* Response to KRB_AS_REQ request */ #define KRB5_TGS_REQ ((krb5_msgtype)12) /* TGS request to server */ #define KRB5_TGS_REP ((krb5_msgtype)13) /* Response to KRB_TGS_REQ req */ #define KRB5_AP_REQ ((krb5_msgtype)14) /* application request to server */ #define KRB5_AP_REP ((krb5_msgtype)15) /* Response to KRB_AP_REQ_MUTUAL */ #define KRB5_SAFE ((krb5_msgtype)20) /* Safe application message */ #define KRB5_PRIV ((krb5_msgtype)21) /* Private application message */ #define KRB5_CRED ((krb5_msgtype)22) /* Credential forwarding message */ #define KRB5_ERROR ((krb5_msgtype)30) /* Error response */ /* LastReq types */ #define KRB5_LRQ_NONE 0 #define KRB5_LRQ_ALL_LAST_TGT 1 #define KRB5_LRQ_ONE_LAST_TGT (-1) #define KRB5_LRQ_ALL_LAST_INITIAL 2 #define KRB5_LRQ_ONE_LAST_INITIAL (-2) #define KRB5_LRQ_ALL_LAST_TGT_ISSUED 3 #define KRB5_LRQ_ONE_LAST_TGT_ISSUED (-3) #define KRB5_LRQ_ALL_LAST_RENEWAL 4 #define KRB5_LRQ_ONE_LAST_RENEWAL (-4) #define KRB5_LRQ_ALL_LAST_REQ 5 #define KRB5_LRQ_ONE_LAST_REQ (-5) #define KRB5_LRQ_ALL_PW_EXPTIME 6 #define KRB5_LRQ_ONE_PW_EXPTIME (-6) /* PADATA types */ #define KRB5_PADATA_NONE 0 #define KRB5_PADATA_AP_REQ 1 #define KRB5_PADATA_TGS_REQ KRB5_PADATA_AP_REQ #define KRB5_PADATA_ENC_TIMESTAMP 2 #define KRB5_PADATA_PW_SALT 3 #if 0 /* Not used */ #define KRB5_PADATA_ENC_ENCKEY 4 /* Key encrypted within itself */ #endif #define KRB5_PADATA_ENC_UNIX_TIME 5 /* timestamp encrypted in key */ #define KRB5_PADATA_ENC_SANDIA_SECURID 6 /* SecurId passcode */ #define KRB5_PADATA_SESAME 7 /* Sesame project */ #define KRB5_PADATA_OSF_DCE 8 /* OSF DCE */ #define KRB5_CYBERSAFE_SECUREID 9 /* Cybersafe */ #define KRB5_PADATA_AFS3_SALT 10 /* Cygnus */ #define KRB5_PADATA_ETYPE_INFO 11 /* Etype info for preauth */ #define KRB5_PADATA_SAM_CHALLENGE 12 /* draft challenge system */ #define KRB5_PADATA_SAM_RESPONSE 13 /* draft challenge system response */ #define KRB5_PADATA_PK_AS_REQ_OLD 14 /* PKINIT */ #define KRB5_PADATA_PK_AS_REP_OLD 15 /* PKINIT */ #define KRB5_PADATA_PK_AS_REQ 16 /* PKINIT */ #define KRB5_PADATA_PK_AS_REP 17 /* PKINIT */ #define KRB5_PADATA_ETYPE_INFO2 19 #define KRB5_PADATA_REFERRAL 25 /* draft referral system */ #define KRB5_PADATA_SAM_CHALLENGE_2 30 /* draft challenge system, updated */ #define KRB5_PADATA_SAM_RESPONSE_2 31 /* draft challenge system, updated */ #define KRB5_SAM_USE_SAD_AS_KEY 0x80000000 #define KRB5_SAM_SEND_ENCRYPTED_SAD 0x40000000 #define KRB5_SAM_MUST_PK_ENCRYPT_SAD 0x20000000 /* currently must be zero */ /* Reserved for SPX pre-authentication. */ #define KRB5_PADATA_DASS 16 /* Transited encoding types */ #define KRB5_DOMAIN_X500_COMPRESS 1 /* alternate authentication types */ #define KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE 64 /* authorization data types */ #define KRB5_AUTHDATA_IF_RELEVANT 1 #define KRB5_AUTHDATA_KDC_ISSUED 4 #define KRB5_AUTHDATA_AND_OR 5 #define KRB5_AUTHDATA_MANDATORY_FOR_KDC 8 #define KRB5_AUTHDATA_INITIAL_VERIFIED_CAS 9 #define KRB5_AUTHDATA_OSF_DCE 64 #define KRB5_AUTHDATA_SESAME 65 #define KRB5_AUTHDATA_WIN2K_PAC 128 #define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /* RFC 4537 */ #define KRB5_AUTHDATA_FX_ARMOR 71 /* password change constants */ #define KRB5_KPASSWD_SUCCESS 0 #define KRB5_KPASSWD_MALFORMED 1 #define KRB5_KPASSWD_HARDERROR 2 #define KRB5_KPASSWD_AUTHERROR 3 #define KRB5_KPASSWD_SOFTERROR 4 /* These are Microsoft's extensions in RFC 3244, and it looks like they'll become standardized, possibly with other additions. */ #define KRB5_KPASSWD_ACCESSDENIED 5 /* unused */ #define KRB5_KPASSWD_BAD_VERSION 6 #define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7 /* unused */ /* * end "proto.h" */ /* Time set */ typedef struct _krb5_ticket_times { krb5_timestamp authtime; /* XXX ? should ktime in KDC_REP == authtime in ticket? otherwise client can't get this */ krb5_timestamp starttime; /* optional in ticket, if not present, use authtime */ krb5_timestamp endtime; krb5_timestamp renew_till; } krb5_ticket_times; /* structure for auth data */ typedef struct _krb5_authdata { krb5_magic magic; krb5_authdatatype ad_type; unsigned int length; krb5_octet *contents; } krb5_authdata; /* structure for transited encoding */ typedef struct _krb5_transited { krb5_magic magic; krb5_octet tr_type; krb5_data tr_contents; } krb5_transited; typedef struct _krb5_enc_tkt_part { krb5_magic magic; /* to-be-encrypted portion */ krb5_flags flags; /* flags */ krb5_keyblock *session; /* session key: includes enctype */ krb5_principal client; /* client name/realm */ krb5_transited transited; /* list of transited realms */ krb5_ticket_times times; /* auth, start, end, renew_till */ krb5_address **caddrs; /* array of ptrs to addresses */ krb5_authdata **authorization_data; /* auth data */ } krb5_enc_tkt_part; typedef struct _krb5_ticket { krb5_magic magic; /* cleartext portion */ krb5_principal server; /* server name/realm */ krb5_enc_data enc_part; /* encryption type, kvno, encrypted encoding */ krb5_enc_tkt_part *enc_part2; /* ptr to decrypted version, if available */ } krb5_ticket; /* the unencrypted version */ typedef struct _krb5_authenticator { krb5_magic magic; krb5_principal client; /* client name/realm */ krb5_checksum *checksum; /* checksum, includes type, optional */ krb5_int32 cusec; /* client usec portion */ krb5_timestamp ctime; /* client sec portion */ krb5_keyblock *subkey; /* true session key, optional */ krb5_ui_4 seq_number; /* sequence #, optional */ krb5_authdata **authorization_data; /* New add by Ari, auth data */ } krb5_authenticator; typedef struct _krb5_tkt_authent { krb5_magic magic; krb5_ticket *ticket; krb5_authenticator *authenticator; krb5_flags ap_options; } krb5_tkt_authent; /* credentials: Ticket, session key, etc. */ typedef struct _krb5_creds { krb5_magic magic; krb5_principal client; /* client's principal identifier */ krb5_principal server; /* server's principal identifier */ krb5_keyblock keyblock; /* session encryption key info */ krb5_ticket_times times; /* lifetime info */ krb5_boolean is_skey; /* true if ticket is encrypted in another ticket's skey */ krb5_flags ticket_flags; /* flags in ticket */ krb5_address * *addresses; /* addrs in ticket */ krb5_data ticket; /* ticket string itself */ krb5_data second_ticket; /* second ticket, if related to ticket (via DUPLICATE-SKEY or ENC-TKT-IN-SKEY) */ krb5_authdata **authdata; /* authorization data */ } krb5_creds; /* Last request fields */ typedef struct _krb5_last_req_entry { krb5_magic magic; krb5_int32 lr_type; krb5_timestamp value; } krb5_last_req_entry; /* pre-authentication data */ typedef struct _krb5_pa_data { krb5_magic magic; krb5_preauthtype pa_type; unsigned int length; krb5_octet *contents; } krb5_pa_data; typedef struct _krb5_kdc_req { krb5_magic magic; krb5_msgtype msg_type; /* AS_REQ or TGS_REQ? */ krb5_pa_data **padata; /* e.g. encoded AP_REQ */ /* real body */ krb5_flags kdc_options; /* requested options */ krb5_principal client; /* includes realm; optional */ krb5_principal server; /* includes realm (only used if no client) */ krb5_timestamp from; /* requested starttime */ krb5_timestamp till; /* requested endtime */ krb5_timestamp rtime; /* (optional) requested renew_till */ krb5_int32 nonce; /* nonce to match request/response */ int nktypes; /* # of ktypes, must be positive */ krb5_enctype *ktype; /* requested enctype(s) */ krb5_address **addresses; /* requested addresses, optional */ krb5_enc_data authorization_data; /* encrypted auth data; OPTIONAL */ krb5_authdata **unenc_authdata; /* unencrypted auth data, if available */ krb5_ticket **second_ticket;/* second ticket array; OPTIONAL */ } krb5_kdc_req; typedef struct _krb5_enc_kdc_rep_part { krb5_magic magic; /* encrypted part: */ krb5_msgtype msg_type; /* krb5 message type */ krb5_keyblock *session; /* session key */ krb5_last_req_entry **last_req; /* array of ptrs to entries */ krb5_int32 nonce; /* nonce from request */ krb5_timestamp key_exp; /* expiration date */ krb5_flags flags; /* ticket flags */ krb5_ticket_times times; /* lifetime info */ krb5_principal server; /* server's principal identifier */ krb5_address **caddrs; /* array of ptrs to addresses, optional */ krb5_pa_data **enc_padata; /* Windows 2000 compat */ } krb5_enc_kdc_rep_part; typedef struct _krb5_kdc_rep { krb5_magic magic; /* cleartext part: */ krb5_msgtype msg_type; /* AS_REP or KDC_REP? */ krb5_pa_data **padata; /* preauthentication data from KDC */ krb5_principal client; /* client's principal identifier */ krb5_ticket *ticket; /* ticket */ krb5_enc_data enc_part; /* encryption type, kvno, encrypted encoding */ krb5_enc_kdc_rep_part *enc_part2;/* unencrypted version, if available */ } krb5_kdc_rep; /* error message structure */ typedef struct _krb5_error { krb5_magic magic; /* some of these may be meaningless in certain contexts */ krb5_timestamp ctime; /* client sec portion; optional */ krb5_int32 cusec; /* client usec portion; optional */ krb5_int32 susec; /* server usec portion */ krb5_timestamp stime; /* server sec portion */ krb5_ui_4 error; /* error code (protocol error #'s) */ krb5_principal client; /* client's principal identifier; optional */ krb5_principal server; /* server's principal identifier */ krb5_data text; /* descriptive text */ krb5_data e_data; /* additional error-describing data */ } krb5_error; typedef struct _krb5_ap_req { krb5_magic magic; krb5_flags ap_options; /* requested options */ krb5_ticket *ticket; /* ticket */ krb5_enc_data authenticator; /* authenticator (already encrypted) */ } krb5_ap_req; typedef struct _krb5_ap_rep { krb5_magic magic; krb5_enc_data enc_part; } krb5_ap_rep; typedef struct _krb5_ap_rep_enc_part { krb5_magic magic; krb5_timestamp ctime; /* client time, seconds portion */ krb5_int32 cusec; /* client time, microseconds portion */ krb5_keyblock *subkey; /* true session key, optional */ krb5_ui_4 seq_number; /* sequence #, optional */ } krb5_ap_rep_enc_part; typedef struct _krb5_response { krb5_magic magic; krb5_octet message_type; krb5_data response; krb5_int32 expected_nonce; /* The expected nonce for KDC_REP messages */ krb5_timestamp request_time; /* When we made the request */ } krb5_response; typedef struct _krb5_cred_info { krb5_magic magic; krb5_keyblock *session; /* session key used to encrypt */ /* ticket */ krb5_principal client; /* client name/realm, optional */ krb5_principal server; /* server name/realm, optional */ krb5_flags flags; /* ticket flags, optional */ krb5_ticket_times times; /* auth, start, end, renew_till, */ /* optional */ krb5_address **caddrs; /* array of ptrs to addresses */ } krb5_cred_info; typedef struct _krb5_cred_enc_part { krb5_magic magic; krb5_int32 nonce; /* nonce, optional */ krb5_timestamp timestamp; /* client time */ krb5_int32 usec; /* microsecond portion of time */ krb5_address *s_address; /* sender address, optional */ krb5_address *r_address; /* recipient address, optional */ krb5_cred_info **ticket_info; } krb5_cred_enc_part; typedef struct _krb5_cred { krb5_magic magic; krb5_ticket **tickets; /* tickets */ krb5_enc_data enc_part; /* encrypted part */ krb5_cred_enc_part *enc_part2; /* unencrypted version, if available*/ } krb5_cred; /* Sandia password generation structures */ typedef struct _passwd_phrase_element { krb5_magic magic; krb5_data *passwd; krb5_data *phrase; } passwd_phrase_element; typedef struct _krb5_pwd_data { krb5_magic magic; int sequence_count; passwd_phrase_element **element; } krb5_pwd_data; /* these need to be here so the typedefs are available for the prototypes */ typedef struct _krb5_pa_svr_referral_data { /* Referred name, only realm is required */ krb5_principal principal; } krb5_pa_svr_referral_data; typedef struct _krb5_pa_server_referral_data { krb5_data *referred_realm; krb5_principal true_principal_name; krb5_principal requested_principal_name; krb5_timestamp referral_valid_until; krb5_checksum rep_cksum; } krb5_pa_server_referral_data; typedef struct _krb5_pa_pac_req { /* TRUE if a PAC should be included in TGS-REP */ krb5_boolean include_pac; } krb5_pa_pac_req; /* * begin "safepriv.h" */ #define KRB5_AUTH_CONTEXT_DO_TIME 0x00000001 #define KRB5_AUTH_CONTEXT_RET_TIME 0x00000002 #define KRB5_AUTH_CONTEXT_DO_SEQUENCE 0x00000004 #define KRB5_AUTH_CONTEXT_RET_SEQUENCE 0x00000008 #define KRB5_AUTH_CONTEXT_PERMIT_ALL 0x00000010 #define KRB5_AUTH_CONTEXT_USE_SUBKEY 0x00000020 typedef struct krb5_replay_data { krb5_timestamp timestamp; krb5_int32 usec; krb5_int32 seq; } krb5_replay_data; /* flags for krb5_auth_con_genaddrs() */ #define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR 0x00000001 #define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR 0x00000002 #define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR 0x00000004 #define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR 0x00000008 /* type of function used as a callback to generate checksum data for * mk_req */ typedef krb5_error_code (KRB5_CALLCONV * krb5_mk_req_checksum_func) (krb5_context, krb5_auth_context , void *, krb5_data **); /* * end "safepriv.h" */ /* * begin "ccache.h" */ typedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */ struct _krb5_ccache; typedef struct _krb5_ccache *krb5_ccache; struct _krb5_cc_ops; typedef struct _krb5_cc_ops krb5_cc_ops; /* for retrieve_cred */ #define KRB5_TC_MATCH_TIMES 0x00000001 #define KRB5_TC_MATCH_IS_SKEY 0x00000002 #define KRB5_TC_MATCH_FLAGS 0x00000004 #define KRB5_TC_MATCH_TIMES_EXACT 0x00000008 #define KRB5_TC_MATCH_FLAGS_EXACT 0x00000010 #define KRB5_TC_MATCH_AUTHDATA 0x00000020 #define KRB5_TC_MATCH_SRV_NAMEONLY 0x00000040 #define KRB5_TC_MATCH_2ND_TKT 0x00000080 #define KRB5_TC_MATCH_KTYPE 0x00000100 #define KRB5_TC_SUPPORTED_KTYPES 0x00000200 /* for set_flags and other functions */ #define KRB5_TC_OPENCLOSE 0x00000001 #define KRB5_TC_NOTICKET 0x00000002 krb5_error_code KRB5_CALLCONV krb5_cc_gen_new (krb5_context context, krb5_ccache *cache); krb5_error_code KRB5_CALLCONV krb5_cc_initialize(krb5_context context, krb5_ccache cache, krb5_principal principal); krb5_error_code KRB5_CALLCONV krb5_cc_destroy (krb5_context context, krb5_ccache cache); krb5_error_code KRB5_CALLCONV krb5_cc_close (krb5_context context, krb5_ccache cache); krb5_error_code KRB5_CALLCONV krb5_cc_store_cred (krb5_context context, krb5_ccache cache, krb5_creds *creds); krb5_error_code KRB5_CALLCONV krb5_cc_retrieve_cred (krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds *mcreds, krb5_creds *creds); krb5_error_code KRB5_CALLCONV krb5_cc_get_principal (krb5_context context, krb5_ccache cache, krb5_principal *principal); krb5_error_code KRB5_CALLCONV krb5_cc_start_seq_get (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor); krb5_error_code KRB5_CALLCONV krb5_cc_next_cred (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, krb5_creds *creds); krb5_error_code KRB5_CALLCONV krb5_cc_end_seq_get (krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor); krb5_error_code KRB5_CALLCONV krb5_cc_remove_cred (krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds *creds); krb5_error_code KRB5_CALLCONV krb5_cc_set_flags (krb5_context context, krb5_ccache cache, krb5_flags flags); krb5_error_code KRB5_CALLCONV krb5_cc_get_flags (krb5_context context, krb5_ccache cache, krb5_flags *flags); const char * KRB5_CALLCONV krb5_cc_get_type (krb5_context context, krb5_ccache cache); /* SUNW14resync - add_cred.c needs this func */ const char * KRB5_CALLCONV krb5_cc_get_name (krb5_context context, krb5_ccache cache); krb5_error_code KRB5_CALLCONV krb5_cc_new_unique( krb5_context context, const char *type, const char *hint, krb5_ccache *id); /* * end "ccache.h" */ /* * begin "rcache.h" */ struct krb5_rc_st; typedef struct krb5_rc_st *krb5_rcache; /* * end "rcache.h" */ /* * begin "keytab.h" */ /* XXX */ #define MAX_KEYTAB_NAME_LEN 1100 /* Long enough for MAXPATHLEN + some extra */ typedef krb5_pointer krb5_kt_cursor; /* XXX */ typedef struct krb5_keytab_entry_st { krb5_magic magic; krb5_principal principal; /* principal of this key */ krb5_timestamp timestamp; /* time entry written to keytable */ krb5_kvno vno; /* key version number */ krb5_keyblock key; /* the secret key */ } krb5_keytab_entry; #if KRB5_PRIVATE struct _krb5_kt_ops; typedef struct _krb5_kt { /* should move into k5-int.h */ krb5_magic magic; const struct _krb5_kt_ops *ops; krb5_pointer data; } *krb5_keytab; #else struct _krb5_kt; typedef struct _krb5_kt *krb5_keytab; #endif char * KRB5_CALLCONV krb5_kt_get_type (krb5_context, krb5_keytab keytab); krb5_error_code KRB5_CALLCONV krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name, unsigned int namelen); krb5_error_code KRB5_CALLCONV krb5_kt_close(krb5_context context, krb5_keytab keytab); krb5_error_code KRB5_CALLCONV krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, krb5_const_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keytab_entry *entry); krb5_error_code KRB5_CALLCONV krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor); krb5_error_code KRB5_CALLCONV krb5_kt_next_entry(krb5_context context, krb5_keytab keytab, krb5_keytab_entry *entry, krb5_kt_cursor *cursor); krb5_error_code KRB5_CALLCONV krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor); /* Solaris Kerberos */ krb5_error_code krb5_kt_find_realm(krb5_context context, krb5_keytab keytab, krb5_principal princ, krb5_data *realm); /* * end "keytab.h" */ /* * begin "func-proto.h" */ /* Solaris Kerberos */ krb5_error_code krb5_init_ef_handle(krb5_context); krb5_error_code krb5_free_ef_handle(krb5_context); krb5_boolean krb5_privacy_allowed(void); /* * Solaris Kerberos: * krb5_copy_keyblock_data is a new routine to hide the details * of a keyblock copy operation. */ krb5_error_code KRB5_CALLCONV krb5_copy_keyblock_data (krb5_context, const krb5_keyblock *, krb5_keyblock *); krb5_error_code KRB5_CALLCONV krb5_init_context (krb5_context *); krb5_error_code KRB5_CALLCONV krb5_init_secure_context (krb5_context *); void KRB5_CALLCONV krb5_free_context (krb5_context); #if KRB5_PRIVATE krb5_error_code krb5_set_default_in_tkt_ktypes (krb5_context, const krb5_enctype *); krb5_error_code krb5_get_default_in_tkt_ktypes (krb5_context, krb5_enctype **); krb5_error_code krb5_set_default_tgs_ktypes (krb5_context, const krb5_enctype *); #endif krb5_error_code KRB5_CALLCONV krb5_set_default_tgs_enctypes (krb5_context, const krb5_enctype *); #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_get_tgs_ktypes (krb5_context, krb5_const_principal, krb5_enctype **); #endif krb5_error_code KRB5_CALLCONV krb5_get_permitted_enctypes (krb5_context, krb5_enctype **); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_ktypes (krb5_context, krb5_enctype *); krb5_boolean krb5_is_permitted_enctype (krb5_context, krb5_enctype); #endif krb5_boolean KRB5_CALLCONV krb5_is_thread_safe(void); /* libkrb.spec */ #if KRB5_PRIVATE krb5_error_code krb5_kdc_rep_decrypt_proc (krb5_context, const krb5_keyblock *, krb5_const_pointer, krb5_kdc_rep * ); krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part (krb5_context, const krb5_keyblock *, krb5_ticket * ); krb5_error_code krb5_get_cred_from_kdc (krb5_context, krb5_ccache, /* not const, as reading may save state */ krb5_creds *, krb5_creds **, krb5_creds *** ); krb5_error_code krb5_get_cred_from_kdc_validate (krb5_context, krb5_ccache, /* not const, as reading may save state */ krb5_creds *, krb5_creds **, krb5_creds *** ); krb5_error_code krb5_get_cred_from_kdc_renew (krb5_context, krb5_ccache, /* not const, as reading may save state */ krb5_creds *, krb5_creds **, krb5_creds *** ); #endif void KRB5_CALLCONV krb5_free_tgt_creds (krb5_context, krb5_creds **); /* XXX too hard to do with const */ #define KRB5_GC_USER_USER 1 /* want user-user ticket */ #define KRB5_GC_CACHED 2 /* want cached ticket only */ krb5_error_code KRB5_CALLCONV krb5_get_credentials (krb5_context, krb5_flags, krb5_ccache, krb5_creds *, krb5_creds **); krb5_error_code KRB5_CALLCONV krb5_get_credentials_validate (krb5_context, krb5_flags, krb5_ccache, krb5_creds *, krb5_creds **); krb5_error_code KRB5_CALLCONV krb5_get_credentials_renew (krb5_context, krb5_flags, krb5_ccache, krb5_creds *, krb5_creds **); #if KRB5_PRIVATE krb5_error_code krb5_get_cred_via_tkt (krb5_context, krb5_creds *, krb5_flags, krb5_address * const *, krb5_creds *, krb5_creds **); #endif krb5_error_code KRB5_CALLCONV krb5_mk_req (krb5_context, krb5_auth_context *, krb5_flags, char *, char *, krb5_data *, krb5_ccache, krb5_data * ); krb5_error_code KRB5_CALLCONV krb5_mk_req_extended (krb5_context, krb5_auth_context *, krb5_flags, krb5_data *, krb5_creds *, krb5_data * ); krb5_error_code KRB5_CALLCONV krb5_mk_rep (krb5_context, krb5_auth_context, krb5_data *); krb5_error_code KRB5_CALLCONV krb5_rd_rep (krb5_context, krb5_auth_context, const krb5_data *, krb5_ap_rep_enc_part **); krb5_error_code KRB5_CALLCONV krb5_mk_error (krb5_context, const krb5_error *, krb5_data * ); krb5_error_code KRB5_CALLCONV krb5_rd_error (krb5_context, const krb5_data *, krb5_error ** ); krb5_error_code KRB5_CALLCONV krb5_rd_safe (krb5_context, krb5_auth_context, const krb5_data *, krb5_data *, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_rd_priv (krb5_context, krb5_auth_context, const krb5_data *, krb5_data *, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_parse_name (krb5_context, const char *, krb5_principal * ); #define KRB5_PRINCIPAL_PARSE_NO_REALM 0x1 #define KRB5_PRINCIPAL_PARSE_REQUIRE_REALM 0x2 #define KRB5_PRINCIPAL_PARSE_ENTERPRISE 0x4 krb5_error_code KRB5_CALLCONV krb5_parse_name_flags (krb5_context, const char *, int, krb5_principal * ); krb5_error_code KRB5_CALLCONV krb5_unparse_name (krb5_context, krb5_const_principal, char ** ); krb5_error_code KRB5_CALLCONV krb5_unparse_name_ext (krb5_context, krb5_const_principal, char **, unsigned int *); #define KRB5_PRINCIPAL_UNPARSE_SHORT 0x1 #define KRB5_PRINCIPAL_UNPARSE_NO_REALM 0x2 #define KRB5_PRINCIPAL_UNPARSE_DISPLAY 0x4 krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags (krb5_context, krb5_const_principal, int, char **); krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags_ext (krb5_context, krb5_const_principal, int, char **, unsigned int *); krb5_error_code KRB5_CALLCONV krb5_set_principal_realm (krb5_context, krb5_principal, const char *); krb5_boolean KRB5_CALLCONV_WRONG krb5_address_search (krb5_context, const krb5_address *, krb5_address * const *); krb5_boolean KRB5_CALLCONV krb5_address_compare (krb5_context, const krb5_address *, const krb5_address *); int KRB5_CALLCONV krb5_address_order (krb5_context, const krb5_address *, const krb5_address *); krb5_boolean KRB5_CALLCONV krb5_realm_compare (krb5_context, krb5_const_principal, krb5_const_principal); krb5_boolean KRB5_CALLCONV krb5_principal_compare (krb5_context, krb5_const_principal, krb5_const_principal); krb5_error_code KRB5_CALLCONV krb5_init_keyblock (krb5_context, krb5_enctype enctype, size_t length, krb5_keyblock **out); /* Initialize a new keyblock and allocate storage * for the contents of the key, which will be freed along * with the keyblock when krb5_free_keyblock is called. * It is legal to pass in a length of 0, in which * case contents are left unallocated. */ /* * Solaris Kerberos * Start - keyblock API (MIT will ship this also in a future release) */ /* * Similiar to krb5_init_keyblock but this routine expects the * keyblock to already be allocated. */ krb5_error_code KRB5_CALLCONV krb5_init_allocated_keyblock (krb5_context, krb5_enctype, unsigned int, krb5_keyblock *); krb5_enctype KRB5_CALLCONV krb5_get_key_enctype (krb5_keyblock *); unsigned int KRB5_CALLCONV krb5_get_key_length (krb5_keyblock *); krb5_octet KRB5_CALLCONV *krb5_get_key_data (krb5_keyblock *); void KRB5_CALLCONV krb5_set_key_enctype (krb5_keyblock *, krb5_enctype); void KRB5_CALLCONV krb5_set_key_data (krb5_keyblock *, krb5_octet *); void KRB5_CALLCONV krb5_set_key_length (krb5_keyblock *, unsigned int); /* * Solaris Kerberos * End - keyblock API */ krb5_error_code KRB5_CALLCONV krb5_copy_keyblock (krb5_context, const krb5_keyblock *, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_copy_keyblock_contents (krb5_context, const krb5_keyblock *, krb5_keyblock *); krb5_error_code KRB5_CALLCONV krb5_copy_creds (krb5_context, const krb5_creds *, krb5_creds **); krb5_error_code KRB5_CALLCONV krb5_copy_data (krb5_context, const krb5_data *, krb5_data **); krb5_error_code KRB5_CALLCONV krb5_copy_principal (krb5_context, krb5_const_principal, krb5_principal *); #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_copy_addr (krb5_context, const krb5_address *, krb5_address **); #endif krb5_error_code KRB5_CALLCONV krb5_copy_addresses (krb5_context, krb5_address * const *, krb5_address ***); krb5_error_code KRB5_CALLCONV krb5_copy_ticket (krb5_context, const krb5_ticket *, krb5_ticket **); krb5_error_code KRB5_CALLCONV krb5_copy_authdata (krb5_context, krb5_authdata * const *, krb5_authdata ***); krb5_error_code KRB5_CALLCONV krb5_merge_authdata (krb5_context, krb5_authdata * const *, krb5_authdata *const *, krb5_authdata ***); /* Merge two authdata arrays, such as the array from a ticket * and authenticator */ krb5_error_code KRB5_CALLCONV krb5_copy_authenticator (krb5_context, const krb5_authenticator *, krb5_authenticator **); krb5_error_code KRB5_CALLCONV krb5_copy_checksum (krb5_context, const krb5_checksum *, krb5_checksum **); #if KRB5_PRIVATE void krb5_init_ets (krb5_context); void krb5_free_ets (krb5_context); krb5_error_code krb5_generate_subkey (krb5_context, const krb5_keyblock *, krb5_keyblock **); krb5_error_code krb5_generate_seq_number (krb5_context, const krb5_keyblock *, krb5_ui_4 *); #endif krb5_error_code KRB5_CALLCONV krb5_get_server_rcache (krb5_context, const krb5_data *, krb5_rcache *); krb5_error_code KRB5_CALLCONV_C krb5_build_principal_ext (krb5_context, krb5_principal *, unsigned int, const char *, ...); krb5_error_code KRB5_CALLCONV_C krb5_build_principal (krb5_context, krb5_principal *, unsigned int, const char *, ...); #ifdef va_start /* XXX depending on varargs include file defining va_start... */ krb5_error_code KRB5_CALLCONV krb5_build_principal_va (krb5_context, krb5_principal, unsigned int, const char *, va_list); #endif krb5_error_code KRB5_CALLCONV krb5_425_conv_principal (krb5_context, const char *name, const char *instance, const char *realm, krb5_principal *princ); krb5_error_code KRB5_CALLCONV krb5_524_conv_principal (krb5_context context, krb5_const_principal princ, char *name, char *inst, char *realm); struct credentials; int KRB5_CALLCONV krb5_524_convert_creds (krb5_context context, krb5_creds *v5creds, struct credentials *v4creds); #if KRB5_DEPRECATED #define krb524_convert_creds_kdc krb5_524_convert_creds #define krb524_init_ets(x) (0) #endif /* libkt.spec */ #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_kt_register (krb5_context, const struct _krb5_kt_ops * ); #endif krb5_error_code KRB5_CALLCONV krb5_kt_resolve (krb5_context, const char *, krb5_keytab * ); krb5_error_code KRB5_CALLCONV krb5_kt_default_name (krb5_context, char *, int ); krb5_error_code KRB5_CALLCONV krb5_kt_default (krb5_context, krb5_keytab * ); krb5_error_code KRB5_CALLCONV krb5_free_keytab_entry_contents (krb5_context, krb5_keytab_entry * ); #if KRB5_PRIVATE /* use krb5_free_keytab_entry_contents instead */ krb5_error_code KRB5_CALLCONV krb5_kt_free_entry (krb5_context, krb5_keytab_entry * ); #endif /* remove and add are functions, so that they can return NOWRITE if not a writable keytab */ krb5_error_code KRB5_CALLCONV krb5_kt_remove_entry (krb5_context, krb5_keytab, krb5_keytab_entry * ); krb5_error_code KRB5_CALLCONV krb5_kt_add_entry (krb5_context, krb5_keytab, krb5_keytab_entry * ); krb5_error_code KRB5_CALLCONV_WRONG krb5_principal2salt (krb5_context, krb5_const_principal, krb5_data *); #if KRB5_PRIVATE krb5_error_code krb5_principal2salt_norealm (krb5_context, krb5_const_principal, krb5_data *); #endif /* librc.spec--see rcache.h */ /* libcc.spec */ krb5_error_code KRB5_CALLCONV krb5_cc_resolve (krb5_context, const char *, krb5_ccache * ); const char * KRB5_CALLCONV krb5_cc_default_name (krb5_context); krb5_error_code KRB5_CALLCONV krb5_cc_set_default_name (krb5_context, const char *); krb5_error_code KRB5_CALLCONV krb5_cc_default (krb5_context, krb5_ccache *); #if KRB5_PRIVATE unsigned int KRB5_CALLCONV krb5_get_notification_message (void); #endif krb5_error_code KRB5_CALLCONV krb5_cc_copy_creds (krb5_context context, krb5_ccache incc, krb5_ccache outcc); /* chk_trans.c */ #if KRB5_PRIVATE krb5_error_code krb5_check_transited_list (krb5_context, const krb5_data *trans, const krb5_data *realm1, const krb5_data *realm2); #endif /* free_rtree.c */ #if KRB5_PRIVATE void krb5_free_realm_tree (krb5_context, krb5_principal *); #endif /* krb5_free.c */ void KRB5_CALLCONV krb5_free_principal (krb5_context, krb5_principal ); void KRB5_CALLCONV krb5_free_authenticator (krb5_context, krb5_authenticator * ); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_authenticator_contents (krb5_context, krb5_authenticator * ); #endif void KRB5_CALLCONV krb5_free_addresses (krb5_context, krb5_address ** ); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_address (krb5_context, krb5_address * ); #endif void KRB5_CALLCONV krb5_free_authdata (krb5_context, krb5_authdata ** ); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_enc_tkt_part (krb5_context, krb5_enc_tkt_part * ); #endif void KRB5_CALLCONV krb5_free_ticket (krb5_context, krb5_ticket * ); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_tickets (krb5_context, krb5_ticket ** ); void KRB5_CALLCONV krb5_free_kdc_req (krb5_context, krb5_kdc_req * ); void KRB5_CALLCONV krb5_free_kdc_rep (krb5_context, krb5_kdc_rep * ); void KRB5_CALLCONV krb5_free_last_req (krb5_context, krb5_last_req_entry ** ); void KRB5_CALLCONV krb5_free_enc_kdc_rep_part (krb5_context, krb5_enc_kdc_rep_part * ); #endif void KRB5_CALLCONV krb5_free_error (krb5_context, krb5_error * ); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_ap_req (krb5_context, krb5_ap_req * ); void KRB5_CALLCONV krb5_free_ap_rep (krb5_context, krb5_ap_rep * ); void KRB5_CALLCONV krb5_free_cred (krb5_context, krb5_cred *); #endif void KRB5_CALLCONV krb5_free_creds (krb5_context, krb5_creds *); void KRB5_CALLCONV krb5_free_cred_contents (krb5_context, krb5_creds *); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_cred_enc_part (krb5_context, krb5_cred_enc_part *); #endif void KRB5_CALLCONV krb5_free_checksum (krb5_context, krb5_checksum *); void KRB5_CALLCONV krb5_free_checksum_contents (krb5_context, krb5_checksum *); void KRB5_CALLCONV krb5_free_keyblock (krb5_context, krb5_keyblock *); void KRB5_CALLCONV krb5_free_keyblock_contents (krb5_context, krb5_keyblock *); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_pa_data (krb5_context, krb5_pa_data **); #endif void KRB5_CALLCONV krb5_free_ap_rep_enc_part (krb5_context, krb5_ap_rep_enc_part *); #if KRB5_PRIVATE void KRB5_CALLCONV krb5_free_tkt_authent (krb5_context, krb5_tkt_authent *); void KRB5_CALLCONV krb5_free_pwd_data (krb5_context, krb5_pwd_data *); void KRB5_CALLCONV krb5_free_pwd_sequences (krb5_context, passwd_phrase_element **); #endif void KRB5_CALLCONV krb5_free_data (krb5_context, krb5_data *); void KRB5_CALLCONV krb5_free_data_contents (krb5_context, krb5_data *); void KRB5_CALLCONV krb5_free_unparsed_name (krb5_context, char *); void KRB5_CALLCONV krb5_free_cksumtypes (krb5_context, krb5_cksumtype *); /* From krb5/os but needed but by the outside world */ krb5_error_code KRB5_CALLCONV krb5_us_timeofday (krb5_context, krb5_int32 *, krb5_int32 * ); krb5_error_code KRB5_CALLCONV krb5_timeofday (krb5_context, krb5_int32 * ); /* get all the addresses of this host */ krb5_error_code KRB5_CALLCONV krb5_os_localaddr (krb5_context, krb5_address ***); krb5_error_code KRB5_CALLCONV krb5_get_default_realm (krb5_context, char ** ); krb5_error_code KRB5_CALLCONV krb5_set_default_realm (krb5_context, const char * ); void KRB5_CALLCONV krb5_free_default_realm (krb5_context, char * ); krb5_error_code KRB5_CALLCONV krb5_sname_to_principal (krb5_context, const char *, const char *, krb5_int32, krb5_principal *); krb5_error_code KRB5_CALLCONV krb5_change_password (krb5_context context, krb5_creds *creds, char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string); krb5_error_code KRB5_CALLCONV krb5_set_password (krb5_context context, krb5_creds *creds, char *newpw, krb5_principal change_password_for, int *result_code, krb5_data *result_code_string, krb5_data *result_string); krb5_error_code KRB5_CALLCONV krb5_set_password_using_ccache (krb5_context context, krb5_ccache ccache, char *newpw, krb5_principal change_password_for, int *result_code, krb5_data *result_code_string, krb5_data *result_string); #if KRB5_PRIVATE krb5_error_code krb5_set_config_files (krb5_context, const char **); krb5_error_code KRB5_CALLCONV krb5_get_default_config_files (char ***filenames); void KRB5_CALLCONV krb5_free_config_files (char **filenames); #endif krb5_error_code KRB5_CALLCONV krb5_get_profile (krb5_context, struct _profile_t * /* profile_t */ *); #if KRB5_PRIVATE krb5_error_code krb5_send_tgs (krb5_context, krb5_flags, const krb5_ticket_times *, const krb5_enctype *, krb5_const_principal, krb5_address * const *, krb5_authdata * const *, krb5_pa_data * const *, const krb5_data *, krb5_creds *, krb5_response * ); krb5_error_code krb5_send_tgs2 (krb5_context, krb5_flags, const krb5_ticket_times *, const krb5_enctype *, krb5_const_principal, krb5_address * const *, krb5_authdata * const *, krb5_pa_data * const *, const krb5_data *, krb5_creds *, krb5_response * , char **); #endif #if KRB5_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_get_in_tkt (krb5_context, krb5_flags, krb5_address * const *, krb5_enctype *, krb5_preauthtype *, krb5_error_code ( * )(krb5_context, krb5_enctype, krb5_data *, krb5_const_pointer, krb5_keyblock **), krb5_const_pointer, krb5_error_code ( * )(krb5_context, const krb5_keyblock *, krb5_const_pointer, krb5_kdc_rep * ), krb5_const_pointer, krb5_creds *, krb5_ccache, krb5_kdc_rep ** ); krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_password (krb5_context, krb5_flags, krb5_address * const *, krb5_enctype *, krb5_preauthtype *, const char *, krb5_ccache, krb5_creds *, krb5_kdc_rep ** ); krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_skey (krb5_context, krb5_flags, krb5_address * const *, krb5_enctype *, krb5_preauthtype *, const krb5_keyblock *, krb5_ccache, krb5_creds *, krb5_kdc_rep ** ); krb5_error_code KRB5_CALLCONV krb5_get_in_tkt_with_keytab (krb5_context, krb5_flags, krb5_address * const *, krb5_enctype *, krb5_preauthtype *, krb5_keytab, krb5_ccache, krb5_creds *, krb5_kdc_rep ** ); #endif /* KRB5_DEPRECATED */ #if KRB5_PRIVATE krb5_error_code krb5_decode_kdc_rep (krb5_context, krb5_data *, const krb5_keyblock *, krb5_kdc_rep ** ); #endif krb5_error_code KRB5_CALLCONV krb5_rd_req (krb5_context, krb5_auth_context *, const krb5_data *, krb5_const_principal, krb5_keytab, krb5_flags *, krb5_ticket **); #if KRB5_PRIVATE krb5_error_code krb5_rd_req_decoded (krb5_context, krb5_auth_context *, const krb5_ap_req *, krb5_const_principal, krb5_keytab, krb5_flags *, krb5_ticket **); krb5_error_code krb5_rd_req_decoded_anyflag (krb5_context, krb5_auth_context *, const krb5_ap_req *, krb5_const_principal, krb5_keytab, krb5_flags *, krb5_ticket **); #endif krb5_error_code KRB5_CALLCONV krb5_kt_read_service_key (krb5_context, krb5_pointer, krb5_principal, krb5_kvno, krb5_enctype, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_mk_safe (krb5_context, krb5_auth_context, const krb5_data *, krb5_data *, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_mk_priv (krb5_context, krb5_auth_context, const krb5_data *, krb5_data *, krb5_replay_data *); #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_cc_register (krb5_context, krb5_cc_ops *, krb5_boolean ); #endif krb5_error_code KRB5_CALLCONV krb5_sendauth (krb5_context, krb5_auth_context *, krb5_pointer, char *, krb5_principal, krb5_principal, krb5_flags, krb5_data *, krb5_creds *, krb5_ccache, krb5_error **, krb5_ap_rep_enc_part **, krb5_creds **); krb5_error_code KRB5_CALLCONV krb5_recvauth (krb5_context, krb5_auth_context *, krb5_pointer, char *, krb5_principal, krb5_int32, krb5_keytab, krb5_ticket **); krb5_error_code KRB5_CALLCONV krb5_recvauth_version (krb5_context, krb5_auth_context *, krb5_pointer, krb5_principal, krb5_int32, krb5_keytab, krb5_ticket **, krb5_data *); #if KRB5_PRIVATE krb5_error_code krb5_walk_realm_tree (krb5_context, const krb5_data *, const krb5_data *, krb5_principal **, int); #endif krb5_error_code KRB5_CALLCONV krb5_mk_ncred (krb5_context, krb5_auth_context, krb5_creds **, krb5_data **, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_mk_1cred (krb5_context, krb5_auth_context, krb5_creds *, krb5_data **, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_rd_cred (krb5_context, krb5_auth_context, krb5_data *, krb5_creds ***, krb5_replay_data *); krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds (krb5_context, krb5_auth_context, char *, krb5_principal, krb5_principal, krb5_ccache, int forwardable, krb5_data *); krb5_error_code KRB5_CALLCONV krb5_auth_con_init (krb5_context, krb5_auth_context *); krb5_error_code KRB5_CALLCONV krb5_auth_con_free (krb5_context, krb5_auth_context); krb5_error_code KRB5_CALLCONV krb5_auth_con_setflags (krb5_context, krb5_auth_context, krb5_int32); krb5_error_code KRB5_CALLCONV krb5_auth_con_getflags (krb5_context, krb5_auth_context, krb5_int32 *); krb5_error_code KRB5_CALLCONV krb5_auth_con_set_checksum_func (krb5_context, krb5_auth_context, krb5_mk_req_checksum_func, void *); krb5_error_code KRB5_CALLCONV krb5_auth_con_get_checksum_func( krb5_context, krb5_auth_context, krb5_mk_req_checksum_func *, void **); krb5_error_code KRB5_CALLCONV_WRONG krb5_auth_con_setaddrs (krb5_context, krb5_auth_context, krb5_address *, krb5_address *); krb5_error_code KRB5_CALLCONV krb5_auth_con_getaddrs (krb5_context, krb5_auth_context, krb5_address **, krb5_address **); krb5_error_code KRB5_CALLCONV krb5_auth_con_setports (krb5_context, krb5_auth_context, krb5_address *, krb5_address *); krb5_error_code KRB5_CALLCONV krb5_auth_con_setuseruserkey (krb5_context, krb5_auth_context, krb5_keyblock *); krb5_error_code KRB5_CALLCONV krb5_auth_con_getkey (krb5_context, krb5_auth_context, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_auth_con_getsendsubkey( krb5_context, krb5_auth_context, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_auth_con_getrecvsubkey( krb5_context, krb5_auth_context, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_auth_con_setsendsubkey( krb5_context, krb5_auth_context, krb5_keyblock *); krb5_error_code KRB5_CALLCONV krb5_auth_con_setrecvsubkey( krb5_context, krb5_auth_context, krb5_keyblock *); #if KRB5_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_auth_con_getlocalsubkey (krb5_context, krb5_auth_context, krb5_keyblock **); krb5_error_code KRB5_CALLCONV krb5_auth_con_getremotesubkey (krb5_context, krb5_auth_context, krb5_keyblock **); #endif #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_auth_con_set_req_cksumtype (krb5_context, krb5_auth_context, krb5_cksumtype); krb5_error_code krb5_auth_con_set_safe_cksumtype (krb5_context, krb5_auth_context, krb5_cksumtype); #endif krb5_error_code KRB5_CALLCONV krb5_auth_con_getlocalseqnumber (krb5_context, krb5_auth_context, krb5_int32 *); krb5_error_code KRB5_CALLCONV krb5_auth_con_getremoteseqnumber (krb5_context, krb5_auth_context, krb5_int32 *); #if KRB5_DEPRECATED krb5_error_code KRB5_CALLCONV krb5_auth_con_initivector (krb5_context, krb5_auth_context); #endif #if KRB5_PRIVATE krb5_error_code krb5_auth_con_setivector (krb5_context, krb5_auth_context, krb5_pointer); krb5_error_code krb5_auth_con_getivector (krb5_context, krb5_auth_context, krb5_pointer *); #endif krb5_error_code KRB5_CALLCONV krb5_auth_con_setrcache (krb5_context, krb5_auth_context, krb5_rcache); krb5_error_code KRB5_CALLCONV_WRONG krb5_auth_con_getrcache (krb5_context, krb5_auth_context, krb5_rcache *); #if KRB5_PRIVATE krb5_error_code krb5_auth_con_setpermetypes (krb5_context, krb5_auth_context, const krb5_enctype *); krb5_error_code krb5_auth_con_getpermetypes (krb5_context, krb5_auth_context, krb5_enctype **); #endif krb5_error_code KRB5_CALLCONV krb5_auth_con_getauthenticator (krb5_context, krb5_auth_context, krb5_authenticator **); #define KRB5_REALM_BRANCH_CHAR '.' /* * end "func-proto.h" */ /* * begin stuff from libos.h */ #if KRB5_PRIVATE krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *); krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *); int krb5_net_read (krb5_context, int , char *, int); int krb5_net_write (krb5_context, int , const char *, int); #endif krb5_error_code KRB5_CALLCONV krb5_read_password (krb5_context, const char *, const char *, char *, unsigned int * ); krb5_error_code KRB5_CALLCONV krb5_aname_to_localname (krb5_context, krb5_const_principal, int, char * ); krb5_error_code KRB5_CALLCONV krb5_get_host_realm (krb5_context, const char *, char *** ); krb5_error_code KRB5_CALLCONV krb5_get_fallback_host_realm (krb5_context, krb5_data *, char *** ); krb5_error_code KRB5_CALLCONV krb5_free_host_realm (krb5_context, char * const * ); #if KRB5_PRIVATE krb5_error_code KRB5_CALLCONV krb5_get_realm_domain (krb5_context, const char *, char ** ); #endif krb5_boolean KRB5_CALLCONV krb5_kuserok (krb5_context, krb5_principal, const char *); krb5_error_code KRB5_CALLCONV krb5_auth_con_genaddrs (krb5_context, krb5_auth_context, int, int); #if KRB5_PRIVATE krb5_error_code krb5_gen_portaddr (krb5_context, const krb5_address *, krb5_const_pointer, krb5_address **); krb5_error_code krb5_gen_replay_name (krb5_context, const krb5_address *, const char *, char **); krb5_error_code krb5_make_fulladdr (krb5_context, krb5_address *, krb5_address *, krb5_address *); #endif krb5_error_code KRB5_CALLCONV krb5_set_real_time (krb5_context, krb5_int32, krb5_int32); #if KRB5_PRIVATE krb5_error_code krb5_set_debugging_time (krb5_context, krb5_int32, krb5_int32); krb5_error_code krb5_use_natural_time (krb5_context); #endif krb5_error_code KRB5_CALLCONV krb5_get_time_offsets (krb5_context, krb5_int32 *, krb5_int32 *); #if KRB5_PRIVATE krb5_error_code krb5_set_time_offsets (krb5_context, krb5_int32, krb5_int32); #endif /* str_conv.c */ krb5_error_code KRB5_CALLCONV krb5_string_to_enctype (char *, krb5_enctype *); krb5_error_code KRB5_CALLCONV krb5_string_to_salttype (char *, krb5_int32 *); krb5_error_code KRB5_CALLCONV krb5_string_to_cksumtype (char *, krb5_cksumtype *); krb5_error_code KRB5_CALLCONV krb5_string_to_timestamp (char *, krb5_timestamp *); krb5_error_code KRB5_CALLCONV krb5_string_to_deltat (char *, krb5_deltat *); krb5_error_code KRB5_CALLCONV krb5_enctype_to_string (krb5_enctype, char *, size_t); /* Solaris Kerberos */ krb5_error_code KRB5_CALLCONV krb5_enctype_to_istring (krb5_enctype, char *, size_t); krb5_error_code KRB5_CALLCONV krb5_salttype_to_string (krb5_int32, char *, size_t); krb5_error_code KRB5_CALLCONV krb5_cksumtype_to_string (krb5_cksumtype, char *, size_t); krb5_error_code KRB5_CALLCONV krb5_timestamp_to_string (krb5_timestamp, char *, size_t); krb5_error_code KRB5_CALLCONV krb5_timestamp_to_sfstring (krb5_timestamp, char *, size_t, char *); krb5_error_code KRB5_CALLCONV krb5_deltat_to_string (krb5_deltat, char *, size_t); /* * end stuff from libos.h */ /* * begin "k5-free.h" */ /* to keep lint happy */ #ifdef _KERNEL #define krb5_xfree_wrap(val,n) kmem_free((char *)(val),n) #else #define krb5_xfree_wrap(val,n) free((char *)(val)) #define krb5_xfree(val) free((char *)(val)) #endif /* * end "k5-free.h" */ /* The name of the Kerberos ticket granting service... and its size */ #define KRB5_TGS_NAME "krbtgt" #define KRB5_TGS_NAME_SIZE 6 /* flags for recvauth */ #define KRB5_RECVAUTH_SKIP_VERSION 0x0001 #define KRB5_RECVAUTH_BADAUTHVERS 0x0002 /* initial ticket api functions */ typedef struct _krb5_prompt { char *prompt; int hidden; krb5_data *reply; } krb5_prompt; typedef krb5_error_code (KRB5_CALLCONV *krb5_prompter_fct)(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]); krb5_error_code KRB5_CALLCONV krb5_prompter_posix (krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[]); typedef struct _krb5_get_init_creds_opt { krb5_flags flags; krb5_deltat tkt_life; krb5_deltat renew_life; int forwardable; int proxiable; krb5_enctype *etype_list; int etype_list_length; krb5_address **address_list; krb5_preauthtype *preauth_list; int preauth_list_length; krb5_data *salt; } krb5_get_init_creds_opt; #define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 #define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002 #define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004 #define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008 #define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010 #define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020 #define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040 #define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 #define KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT 0x0100 krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_alloc (krb5_context context, krb5_get_init_creds_opt **opt); void KRB5_CALLCONV krb5_get_init_creds_opt_free (krb5_context context, krb5_get_init_creds_opt *opt); void KRB5_CALLCONV krb5_get_init_creds_opt_init (krb5_get_init_creds_opt *opt); void KRB5_CALLCONV krb5_get_init_creds_opt_set_tkt_life (krb5_get_init_creds_opt *opt, krb5_deltat tkt_life); void KRB5_CALLCONV krb5_get_init_creds_opt_set_renew_life (krb5_get_init_creds_opt *opt, krb5_deltat renew_life); void KRB5_CALLCONV krb5_get_init_creds_opt_set_forwardable (krb5_get_init_creds_opt *opt, int forwardable); void KRB5_CALLCONV krb5_get_init_creds_opt_set_proxiable (krb5_get_init_creds_opt *opt, int proxiable); void KRB5_CALLCONV krb5_get_init_creds_opt_set_etype_list (krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length); void KRB5_CALLCONV krb5_get_init_creds_opt_set_address_list (krb5_get_init_creds_opt *opt, krb5_address **addresses); void KRB5_CALLCONV krb5_get_init_creds_opt_set_preauth_list (krb5_get_init_creds_opt *opt, krb5_preauthtype *preauth_list, int preauth_list_length); void KRB5_CALLCONV krb5_get_init_creds_opt_set_salt (krb5_get_init_creds_opt *opt, krb5_data *salt); void KRB5_CALLCONV krb5_get_init_creds_opt_set_change_password_prompt (krb5_get_init_creds_opt *opt, int prompt); /* Generic preauth option attribute/value pairs */ typedef struct _krb5_gic_opt_pa_data { char *attr; char *value; } krb5_gic_opt_pa_data; /* * This function allows the caller to supply options to preauth * plugins. Preauth plugin modules are given a chance to look * at each option at the time this function is called in ordre * to check the validity of the option. * The 'opt' pointer supplied to this function must have been * obtained using krb5_get_init_creds_opt_alloc() */ krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_pa (krb5_context context, krb5_get_init_creds_opt *opt, const char *attr, const char *value); krb5_error_code KRB5_CALLCONV krb5_get_init_creds_password (krb5_context context, krb5_creds *creds, krb5_principal client, char *password, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, char *in_tkt_service, krb5_get_init_creds_opt *k5_gic_options); krb5_error_code KRB5_CALLCONV krb5_get_init_creds_keytab (krb5_context context, krb5_creds *creds, krb5_principal client, krb5_keytab arg_keytab, krb5_deltat start_time, char *in_tkt_service, krb5_get_init_creds_opt *k5_gic_options); typedef struct _krb5_verify_init_creds_opt { krb5_flags flags; int ap_req_nofail; } krb5_verify_init_creds_opt; #define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001 void KRB5_CALLCONV krb5_verify_init_creds_opt_init (krb5_verify_init_creds_opt *k5_vic_options); void KRB5_CALLCONV krb5_verify_init_creds_opt_set_ap_req_nofail (krb5_verify_init_creds_opt *k5_vic_options, int ap_req_nofail); krb5_error_code KRB5_CALLCONV krb5_verify_init_creds (krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab, krb5_ccache *ccache, krb5_verify_init_creds_opt *k5_vic_options); krb5_error_code KRB5_CALLCONV krb5_get_validated_creds (krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, char *in_tkt_service); krb5_error_code KRB5_CALLCONV krb5_get_renewed_creds (krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, char *in_tkt_service); krb5_error_code KRB5_CALLCONV krb5_decode_ticket (const krb5_data *code, krb5_ticket **rep); void KRB5_CALLCONV krb5_appdefault_string (krb5_context context, const char *appname, const krb5_data *realm, const char *option, const char *default_value, char ** ret_value); void KRB5_CALLCONV krb5_appdefault_boolean (krb5_context context, const char *appname, const krb5_data *realm, const char *option, int default_value, int *ret_value); #if KRB5_PRIVATE /* * The realm iterator functions */ krb5_error_code KRB5_CALLCONV krb5_realm_iterator_create (krb5_context context, void **iter_p); krb5_error_code KRB5_CALLCONV krb5_realm_iterator (krb5_context context, void **iter_p, char **ret_realm); void KRB5_CALLCONV krb5_realm_iterator_free (krb5_context context, void **iter_p); void KRB5_CALLCONV krb5_free_realm_string (krb5_context context, char *str); #endif /* * The realm iterator functions */ krb5_error_code KRB5_CALLCONV krb5_realm_iterator_create (krb5_context context, void **iter_p); krb5_error_code KRB5_CALLCONV krb5_realm_iterator (krb5_context context, void **iter_p, char **ret_realm); void KRB5_CALLCONV krb5_realm_iterator_free (krb5_context context, void **iter_p); void KRB5_CALLCONV krb5_free_realm_string (krb5_context context, char *str); /* * Prompter enhancements */ #define KRB5_PROMPT_TYPE_PASSWORD 0x1 #define KRB5_PROMPT_TYPE_NEW_PASSWORD 0x2 #define KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN 0x3 #define KRB5_PROMPT_TYPE_PREAUTH 0x4 typedef krb5_int32 krb5_prompt_type; krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types (krb5_context context); /* Error reporting */ void KRB5_CALLCONV_C krb5_set_error_message (krb5_context, krb5_error_code, const char *, ...); #ifdef va_start void KRB5_CALLCONV krb5_vset_error_message (krb5_context, krb5_error_code, const char *, va_list); #endif /* * The behavior of krb5_get_error_message is only defined the first * time it is called after a failed call to a krb5 function using the * same context, and only when the error code passed in is the same as * that returned by the krb5 function. Future versions may return the * same string for the second and following calls. * * The string returned by this function must be freed using * krb5_free_error_message. */ const char * KRB5_CALLCONV krb5_get_error_message (krb5_context, krb5_error_code); void KRB5_CALLCONV krb5_free_error_message (krb5_context, const char *); void KRB5_CALLCONV krb5_clear_error_message (krb5_context); krb5_error_code KRB5_CALLCONV krb5_decode_authdata_container(krb5_context context, krb5_authdatatype type, const krb5_authdata *container, krb5_authdata ***authdata); krb5_error_code KRB5_CALLCONV krb5_encode_authdata_container(krb5_context context, krb5_authdatatype type, krb5_authdata * const*authdata, krb5_authdata ***container); /* * Windows PAC */ struct krb5_pac_data; typedef struct krb5_pac_data *krb5_pac; krb5_error_code KRB5_CALLCONV krb5_pac_add_buffer (krb5_context context, krb5_pac pac, krb5_ui_4 type, const krb5_data *data); void KRB5_CALLCONV krb5_pac_free (krb5_context context, krb5_pac pac); krb5_error_code KRB5_CALLCONV krb5_pac_get_buffer (krb5_context context, krb5_pac pac, krb5_ui_4 type, krb5_data *data); krb5_error_code KRB5_CALLCONV krb5_pac_get_types (krb5_context context, krb5_pac pac, size_t *len, krb5_ui_4 **types); krb5_error_code KRB5_CALLCONV krb5_pac_init (krb5_context context, krb5_pac *pac); krb5_error_code KRB5_CALLCONV krb5_pac_parse (krb5_context context, const void *ptr, size_t len, krb5_pac *pac); krb5_error_code KRB5_CALLCONV krb5_pac_verify (krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock *server, const krb5_keyblock *privsvr); #if TARGET_OS_MAC # pragma pack(pop) #endif KRB5INT_END_DECLS /* Don't use this! We're going to phase it out. It's just here to keep applications from breaking right away. */ #define krb5_const const #endif /* KRB5_GENERAL__ */ /* * Solaris Kerberos: the following differs from the MIT krb5.hin as that file is * processed to produce their krb5.h. We do not process a krb5.hin so our * krb5.h is manually edited. */ /* * krb5_err.h: * This file is automatically generated; please do not edit it. */ #define KRB5KDC_ERR_NONE (-1765328384L) #define KRB5KDC_ERR_NAME_EXP (-1765328383L) #define KRB5KDC_ERR_SERVICE_EXP (-1765328382L) #define KRB5KDC_ERR_BAD_PVNO (-1765328381L) #define KRB5KDC_ERR_C_OLD_MAST_KVNO (-1765328380L) #define KRB5KDC_ERR_S_OLD_MAST_KVNO (-1765328379L) #define KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN (-1765328378L) #define KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN (-1765328377L) #define KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE (-1765328376L) #define KRB5KDC_ERR_NULL_KEY (-1765328375L) #define KRB5KDC_ERR_CANNOT_POSTDATE (-1765328374L) #define KRB5KDC_ERR_NEVER_VALID (-1765328373L) #define KRB5KDC_ERR_POLICY (-1765328372L) #define KRB5KDC_ERR_BADOPTION (-1765328371L) #define KRB5KDC_ERR_ETYPE_NOSUPP (-1765328370L) #define KRB5KDC_ERR_SUMTYPE_NOSUPP (-1765328369L) #define KRB5KDC_ERR_PADATA_TYPE_NOSUPP (-1765328368L) #define KRB5KDC_ERR_TRTYPE_NOSUPP (-1765328367L) #define KRB5KDC_ERR_CLIENT_REVOKED (-1765328366L) #define KRB5KDC_ERR_SERVICE_REVOKED (-1765328365L) #define KRB5KDC_ERR_TGT_REVOKED (-1765328364L) #define KRB5KDC_ERR_CLIENT_NOTYET (-1765328363L) #define KRB5KDC_ERR_SERVICE_NOTYET (-1765328362L) #define KRB5KDC_ERR_KEY_EXP (-1765328361L) #define KRB5KDC_ERR_PREAUTH_FAILED (-1765328360L) #define KRB5KDC_ERR_PREAUTH_REQUIRED (-1765328359L) #define KRB5KDC_ERR_SERVER_NOMATCH (-1765328358L) #define KRB5KDC_ERR_MUST_USE_USER2USER (-1765328357L) #define KRB5KDC_ERR_PATH_NOT_ACCEPTED (-1765328356L) #define KRB5KDC_ERR_SVC_UNAVAILABLE (-1765328355L) #define KRB5PLACEHOLD_30 (-1765328354L) #define KRB5KRB_AP_ERR_BAD_INTEGRITY (-1765328353L) #define KRB5KRB_AP_ERR_TKT_EXPIRED (-1765328352L) #define KRB5KRB_AP_ERR_TKT_NYV (-1765328351L) #define KRB5KRB_AP_ERR_REPEAT (-1765328350L) #define KRB5KRB_AP_ERR_NOT_US (-1765328349L) #define KRB5KRB_AP_ERR_BADMATCH (-1765328348L) #define KRB5KRB_AP_ERR_SKEW (-1765328347L) #define KRB5KRB_AP_ERR_BADADDR (-1765328346L) #define KRB5KRB_AP_ERR_BADVERSION (-1765328345L) #define KRB5KRB_AP_ERR_MSG_TYPE (-1765328344L) #define KRB5KRB_AP_ERR_MODIFIED (-1765328343L) #define KRB5KRB_AP_ERR_BADORDER (-1765328342L) #define KRB5KRB_AP_ERR_ILL_CR_TKT (-1765328341L) #define KRB5KRB_AP_ERR_BADKEYVER (-1765328340L) #define KRB5KRB_AP_ERR_NOKEY (-1765328339L) #define KRB5KRB_AP_ERR_MUT_FAIL (-1765328338L) #define KRB5KRB_AP_ERR_BADDIRECTION (-1765328337L) #define KRB5KRB_AP_ERR_METHOD (-1765328336L) #define KRB5KRB_AP_ERR_BADSEQ (-1765328335L) #define KRB5KRB_AP_ERR_INAPP_CKSUM (-1765328334L) #define KRB5KRB_AP_PATH_NOT_ACCEPTED (-1765328333L) #define KRB5KRB_ERR_RESPONSE_TOO_BIG (-1765328332L) #define KRB5PLACEHOLD_53 (-1765328331L) #define KRB5PLACEHOLD_54 (-1765328330L) #define KRB5PLACEHOLD_55 (-1765328329L) #define KRB5PLACEHOLD_56 (-1765328328L) #define KRB5PLACEHOLD_57 (-1765328327L) #define KRB5PLACEHOLD_58 (-1765328326L) #define KRB5PLACEHOLD_59 (-1765328325L) #define KRB5KRB_ERR_GENERIC (-1765328324L) #define KRB5KRB_ERR_FIELD_TOOLONG (-1765328323L) #define KRB5KDC_ERR_CLIENT_NOT_TRUSTED (-1765328322L) #define KRB5KDC_ERR_KDC_NOT_TRUSTED (-1765328321L) #define KRB5KDC_ERR_INVALID_SIG (-1765328320L) #define KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED (-1765328319L) #define KRB5KDC_ERR_CERTIFICATE_MISMATCH (-1765328318L) #define KRB5KRB_AP_ERR_NO_TGT (-1765328317L) #define KRB5KDC_ERR_WRONG_REALM (-1765328316L) #define KRB5KRB_AP_ERR_USER_TO_USER_REQUIRED (-1765328315L) #define KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE (-1765328314L) #define KRB5KDC_ERR_INVALID_CERTIFICATE (-1765328313L) #define KRB5KDC_ERR_REVOKED_CERTIFICATE (-1765328312L) #define KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN (-1765328311L) #define KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE (-1765328310L) #define KRB5KDC_ERR_CLIENT_NAME_MISMATCH (-1765328309L) #define KRB5KDC_ERR_KDC_NAME_MISMATCH (-1765328308L) #define KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE (-1765328307L) #define KRB5KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED (-1765328306L) #define KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED (-1765328305L) #define KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED (-1765328304L) #define KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED (-1765328303L) #define KRB5PLACEHOLD_82 (-1765328302L) #define KRB5PLACEHOLD_83 (-1765328301L) #define KRB5PLACEHOLD_84 (-1765328300L) #define KRB5PLACEHOLD_85 (-1765328299L) #define KRB5PLACEHOLD_86 (-1765328298L) #define KRB5PLACEHOLD_87 (-1765328297L) #define KRB5PLACEHOLD_88 (-1765328296L) #define KRB5PLACEHOLD_89 (-1765328295L) #define KRB5PLACEHOLD_90 (-1765328294L) #define KRB5PLACEHOLD_91 (-1765328293L) #define KRB5PLACEHOLD_92 (-1765328292L) #define KRB5PLACEHOLD_93 (-1765328291L) #define KRB5PLACEHOLD_94 (-1765328290L) #define KRB5PLACEHOLD_95 (-1765328289L) #define KRB5PLACEHOLD_96 (-1765328288L) #define KRB5PLACEHOLD_97 (-1765328287L) #define KRB5PLACEHOLD_98 (-1765328286L) #define KRB5PLACEHOLD_99 (-1765328285L) #define KRB5PLACEHOLD_100 (-1765328284L) #define KRB5PLACEHOLD_101 (-1765328283L) #define KRB5PLACEHOLD_102 (-1765328282L) #define KRB5PLACEHOLD_103 (-1765328281L) #define KRB5PLACEHOLD_104 (-1765328280L) #define KRB5PLACEHOLD_105 (-1765328279L) #define KRB5PLACEHOLD_106 (-1765328278L) #define KRB5PLACEHOLD_107 (-1765328277L) #define KRB5PLACEHOLD_108 (-1765328276L) #define KRB5PLACEHOLD_109 (-1765328275L) #define KRB5PLACEHOLD_110 (-1765328274L) #define KRB5PLACEHOLD_111 (-1765328273L) #define KRB5PLACEHOLD_112 (-1765328272L) #define KRB5PLACEHOLD_113 (-1765328271L) #define KRB5PLACEHOLD_114 (-1765328270L) #define KRB5PLACEHOLD_115 (-1765328269L) #define KRB5PLACEHOLD_116 (-1765328268L) #define KRB5PLACEHOLD_117 (-1765328267L) #define KRB5PLACEHOLD_118 (-1765328266L) #define KRB5PLACEHOLD_119 (-1765328265L) #define KRB5PLACEHOLD_120 (-1765328264L) #define KRB5PLACEHOLD_121 (-1765328263L) #define KRB5PLACEHOLD_122 (-1765328262L) #define KRB5PLACEHOLD_123 (-1765328261L) #define KRB5PLACEHOLD_124 (-1765328260L) #define KRB5PLACEHOLD_125 (-1765328259L) #define KRB5PLACEHOLD_126 (-1765328258L) #define KRB5PLACEHOLD_127 (-1765328257L) #define KRB5_ERR_RCSID (-1765328256L) #define KRB5_LIBOS_BADLOCKFLAG (-1765328255L) #define KRB5_LIBOS_CANTREADPWD (-1765328254L) #define KRB5_LIBOS_BADPWDMATCH (-1765328253L) #define KRB5_LIBOS_PWDINTR (-1765328252L) #define KRB5_PARSE_ILLCHAR (-1765328251L) #define KRB5_PARSE_MALFORMED (-1765328250L) #define KRB5_CONFIG_CANTOPEN (-1765328249L) #define KRB5_CONFIG_BADFORMAT (-1765328248L) #define KRB5_CONFIG_NOTENUFSPACE (-1765328247L) #define KRB5_BADMSGTYPE (-1765328246L) #define KRB5_CC_BADNAME (-1765328245L) #define KRB5_CC_UNKNOWN_TYPE (-1765328244L) #define KRB5_CC_NOTFOUND (-1765328243L) #define KRB5_CC_END (-1765328242L) #define KRB5_NO_TKT_SUPPLIED (-1765328241L) #define KRB5KRB_AP_WRONG_PRINC (-1765328240L) #define KRB5KRB_AP_ERR_TKT_INVALID (-1765328239L) #define KRB5_PRINC_NOMATCH (-1765328238L) #define KRB5_KDCREP_MODIFIED (-1765328237L) #define KRB5_KDCREP_SKEW (-1765328236L) #define KRB5_IN_TKT_REALM_MISMATCH (-1765328235L) #define KRB5_PROG_ETYPE_NOSUPP (-1765328234L) #define KRB5_PROG_KEYTYPE_NOSUPP (-1765328233L) #define KRB5_WRONG_ETYPE (-1765328232L) #define KRB5_PROG_SUMTYPE_NOSUPP (-1765328231L) #define KRB5_REALM_UNKNOWN (-1765328230L) #define KRB5_SERVICE_UNKNOWN (-1765328229L) #define KRB5_KDC_UNREACH (-1765328228L) #define KRB5_NO_LOCALNAME (-1765328227L) #define KRB5_MUTUAL_FAILED (-1765328226L) #define KRB5_RC_TYPE_EXISTS (-1765328225L) #define KRB5_RC_MALLOC (-1765328224L) #define KRB5_RC_TYPE_NOTFOUND (-1765328223L) #define KRB5_RC_UNKNOWN (-1765328222L) #define KRB5_RC_REPLAY (-1765328221L) #define KRB5_RC_IO (-1765328220L) #define KRB5_RC_NOIO (-1765328219L) #define KRB5_RC_PARSE (-1765328218L) #define KRB5_RC_IO_EOF (-1765328217L) #define KRB5_RC_IO_MALLOC (-1765328216L) #define KRB5_RC_IO_PERM (-1765328215L) #define KRB5_RC_IO_IO (-1765328214L) #define KRB5_RC_IO_UNKNOWN (-1765328213L) #define KRB5_RC_IO_SPACE (-1765328212L) #define KRB5_TRANS_CANTOPEN (-1765328211L) #define KRB5_TRANS_BADFORMAT (-1765328210L) #define KRB5_LNAME_CANTOPEN (-1765328209L) #define KRB5_LNAME_NOTRANS (-1765328208L) #define KRB5_LNAME_BADFORMAT (-1765328207L) #define KRB5_CRYPTO_INTERNAL (-1765328206L) #define KRB5_KT_BADNAME (-1765328205L) #define KRB5_KT_UNKNOWN_TYPE (-1765328204L) #define KRB5_KT_NOTFOUND (-1765328203L) #define KRB5_KT_END (-1765328202L) #define KRB5_KT_NOWRITE (-1765328201L) #define KRB5_KT_IOERR (-1765328200L) #define KRB5_NO_TKT_IN_RLM (-1765328199L) #define KRB5DES_BAD_KEYPAR (-1765328198L) #define KRB5DES_WEAK_KEY (-1765328197L) #define KRB5_BAD_ENCTYPE (-1765328196L) #define KRB5_BAD_KEYSIZE (-1765328195L) #define KRB5_BAD_MSIZE (-1765328194L) #define KRB5_CC_TYPE_EXISTS (-1765328193L) #define KRB5_KT_TYPE_EXISTS (-1765328192L) #define KRB5_CC_IO (-1765328191L) #define KRB5_FCC_PERM (-1765328190L) #define KRB5_FCC_NOFILE (-1765328189L) #define KRB5_FCC_INTERNAL (-1765328188L) #define KRB5_CC_WRITE (-1765328187L) #define KRB5_CC_NOMEM (-1765328186L) #define KRB5_CC_FORMAT (-1765328185L) #define KRB5_CC_NOT_KTYPE (-1765328184L) #define KRB5_INVALID_FLAGS (-1765328183L) #define KRB5_NO_2ND_TKT (-1765328182L) #define KRB5_NOCREDS_SUPPLIED (-1765328181L) #define KRB5_SENDAUTH_BADAUTHVERS (-1765328180L) #define KRB5_SENDAUTH_BADAPPLVERS (-1765328179L) #define KRB5_SENDAUTH_BADRESPONSE (-1765328178L) #define KRB5_SENDAUTH_REJECTED (-1765328177L) #define KRB5_PREAUTH_BAD_TYPE (-1765328176L) #define KRB5_PREAUTH_NO_KEY (-1765328175L) #define KRB5_PREAUTH_FAILED (-1765328174L) #define KRB5_RCACHE_BADVNO (-1765328173L) #define KRB5_CCACHE_BADVNO (-1765328172L) #define KRB5_KEYTAB_BADVNO (-1765328171L) #define KRB5_PROG_ATYPE_NOSUPP (-1765328170L) #define KRB5_RC_REQUIRED (-1765328169L) #define KRB5_ERR_BAD_HOSTNAME (-1765328168L) #define KRB5_ERR_HOST_REALM_UNKNOWN (-1765328167L) #define KRB5_SNAME_UNSUPP_NAMETYPE (-1765328166L) #define KRB5KRB_AP_ERR_V4_REPLY (-1765328165L) #define KRB5_REALM_CANT_RESOLVE (-1765328164L) #define KRB5_TKT_NOT_FORWARDABLE (-1765328163L) #define KRB5_FWD_BAD_PRINCIPAL (-1765328162L) #define KRB5_GET_IN_TKT_LOOP (-1765328161L) #define KRB5_CONFIG_NODEFREALM (-1765328160L) #define KRB5_SAM_UNSUPPORTED (-1765328159L) #define KRB5_SAM_INVALID_ETYPE (-1765328158L) #define KRB5_SAM_NO_CHECKSUM (-1765328157L) #define KRB5_SAM_BAD_CHECKSUM (-1765328156L) #define KRB5_KT_NAME_TOOLONG (-1765328155L) #define KRB5_KT_KVNONOTFOUND (-1765328154L) #define KRB5_APPL_EXPIRED (-1765328153L) #define KRB5_LIB_EXPIRED (-1765328152L) #define KRB5_CHPW_PWDNULL (-1765328151L) #define KRB5_CHPW_FAIL (-1765328150L) #define KRB5_KT_FORMAT (-1765328149L) #define KRB5_NOPERM_ETYPE (-1765328148L) #define KRB5_CONFIG_ETYPE_NOSUPP (-1765328147L) #define KRB5_OBSOLETE_FN (-1765328146L) #define KRB5_EAI_FAIL (-1765328145L) #define KRB5_EAI_NODATA (-1765328144L) #define KRB5_EAI_NONAME (-1765328143L) #define KRB5_EAI_SERVICE (-1765328142L) #define KRB5_ERR_NUMERIC_REALM (-1765328141L) #define KRB5_ERR_BAD_S2K_PARAMS (-1765328140L) #define KRB5_ERR_NO_SERVICE (-1765328139L) #define KRB5_CC_READONLY (-1765328138L) #define KRB5_CC_NOSUPP (-1765328137L) /* NOTE! error values should not collide */ /* XXX Note KRB5_RC_BADNAME and KRB5_CONF_NOT_CONFIGURED are Solaris specific */ #define KRB5_RC_BADNAME (-1765328136L) #define KRB5_CONF_NOT_CONFIGURED (-1765328135L) #ifdef _KERNEL /* XXX Note KRB5_KEF_ERROR and PKCS_ERR are Solaris specific */ #define KRB5_KEF_ERROR (-1765328134L) #else #define PKCS_ERR (-1765328134L) #endif /* _KERNEL */ #define KRB5_DELTAT_BADFORMAT (-1765328133L) #define KRB5_PLUGIN_NO_HANDLE (-1765328132L) #define KRB5_PLUGIN_OP_NOTSUPP (-1765328131L) /* SUNW17PACresync */ #define KRB5_ERR_INVALID_UTF8 (-1765328130L) #define KRB5_ERR_FAST_REQUIRED (-1765328129L) #define KRB5_LOCAL_ADDR_REQUIRED (-1765328128L) #define KRB5_REMOTE_ADDR_REQUIRED (-1765328127L) #define ERROR_TABLE_BASE_krb5 (-1765328384L) /* for compatibility with older versions... */ #define krb5_err_base ERROR_TABLE_BASE_krb5 /* * kdb5_err.h: * This file is automatically generated; please do not edit it. */ #define KRB5_KDB_RCSID (-1780008448L) #define KRB5_KDB_INUSE (-1780008447L) #define KRB5_KDB_UK_SERROR (-1780008446L) #define KRB5_KDB_UK_RERROR (-1780008445L) #define KRB5_KDB_UNAUTH (-1780008444L) #define KRB5_KDB_NOENTRY (-1780008443L) #define KRB5_KDB_ILL_WILDCARD (-1780008442L) #define KRB5_KDB_DB_INUSE (-1780008441L) #define KRB5_KDB_DB_CHANGED (-1780008440L) #define KRB5_KDB_TRUNCATED_RECORD (-1780008439L) #define KRB5_KDB_RECURSIVELOCK (-1780008438L) #define KRB5_KDB_NOTLOCKED (-1780008437L) #define KRB5_KDB_BADLOCKMODE (-1780008436L) #define KRB5_KDB_DBNOTINITED (-1780008435L) #define KRB5_KDB_DBINITED (-1780008434L) #define KRB5_KDB_ILLDIRECTION (-1780008433L) #define KRB5_KDB_NOMASTERKEY (-1780008432L) #define KRB5_KDB_BADMASTERKEY (-1780008431L) #define KRB5_KDB_INVALIDKEYSIZE (-1780008430L) #define KRB5_KDB_CANTREAD_STORED (-1780008429L) #define KRB5_KDB_BADSTORED_MKEY (-1780008428L) #define KRB5_KDB_CANTLOCK_DB (-1780008427L) #define KRB5_KDB_DB_CORRUPT (-1780008426L) #define KRB5_KDB_BAD_VERSION (-1780008425L) #define KRB5_KDB_BAD_SALTTYPE (-1780008424L) #define KRB5_KDB_BAD_ENCTYPE (-1780008423L) #define KRB5_KDB_BAD_CREATEFLAGS (-1780008422L) #define KRB5_KDB_NO_PERMITTED_KEY (-1780008421L) #define KRB5_KDB_NO_MATCHING_KEY (-1780008420L) /* * Incremental propagation error codes */ #define KRB5_LOG_CONV (-1780008419L) #define KRB5_LOG_UNSTABLE (-1780008418L) #define KRB5_LOG_CORRUPT (-1780008417L) #define KRB5_LOG_ERROR (-1780008416L) #define KRB5_KDB_DBTYPE_NOTFOUND (-1780008415L) #define KRB5_KDB_DBTYPE_NOSUP (-1780008414L) #define KRB5_KDB_DBTYPE_INIT (-1780008413L) #define KRB5_KDB_SERVER_INTERNAL_ERR (-1780008412L) #define KRB5_KDB_ACCESS_ERROR (-1780008411L) #define KRB5_KDB_INTERNAL_ERROR (-1780008410L) #define KRB5_KDB_CONSTRAINT_VIOLATION (-1780008409L) #define ERROR_TABLE_BASE_kdb5 (-1780008448L) /* for compatibility with older versions... */ #define kdb5_err_base ERROR_TABLE_BASE_kdb5 /* * kv5m_err.h: * This file is automatically generated; please do not edit it. */ #define KV5M_NONE (-1760647424L) #define KV5M_PRINCIPAL (-1760647423L) #define KV5M_DATA (-1760647422L) #define KV5M_KEYBLOCK (-1760647421L) #define KV5M_CHECKSUM (-1760647420L) #define KV5M_ENCRYPT_BLOCK (-1760647419L) #define KV5M_ENC_DATA (-1760647418L) #define KV5M_CRYPTOSYSTEM_ENTRY (-1760647417L) #define KV5M_CS_TABLE_ENTRY (-1760647416L) #define KV5M_CHECKSUM_ENTRY (-1760647415L) #define KV5M_AUTHDATA (-1760647414L) #define KV5M_TRANSITED (-1760647413L) #define KV5M_ENC_TKT_PART (-1760647412L) #define KV5M_TICKET (-1760647411L) #define KV5M_AUTHENTICATOR (-1760647410L) #define KV5M_TKT_AUTHENT (-1760647409L) #define KV5M_CREDS (-1760647408L) #define KV5M_LAST_REQ_ENTRY (-1760647407L) #define KV5M_PA_DATA (-1760647406L) #define KV5M_KDC_REQ (-1760647405L) #define KV5M_ENC_KDC_REP_PART (-1760647404L) #define KV5M_KDC_REP (-1760647403L) #define KV5M_ERROR (-1760647402L) #define KV5M_AP_REQ (-1760647401L) #define KV5M_AP_REP (-1760647400L) #define KV5M_AP_REP_ENC_PART (-1760647399L) #define KV5M_RESPONSE (-1760647398L) #define KV5M_SAFE (-1760647397L) #define KV5M_PRIV (-1760647396L) #define KV5M_PRIV_ENC_PART (-1760647395L) #define KV5M_CRED (-1760647394L) #define KV5M_CRED_INFO (-1760647393L) #define KV5M_CRED_ENC_PART (-1760647392L) #define KV5M_PWD_DATA (-1760647391L) #define KV5M_ADDRESS (-1760647390L) #define KV5M_KEYTAB_ENTRY (-1760647389L) #define KV5M_CONTEXT (-1760647388L) #define KV5M_OS_CONTEXT (-1760647387L) #define KV5M_ALT_METHOD (-1760647386L) #define KV5M_ETYPE_INFO_ENTRY (-1760647385L) #define KV5M_DB_CONTEXT (-1760647384L) #define KV5M_AUTH_CONTEXT (-1760647383L) #define KV5M_KEYTAB (-1760647382L) #define KV5M_RCACHE (-1760647381L) #define KV5M_CCACHE (-1760647380L) #define KV5M_PREAUTH_OPS (-1760647379L) #define KV5M_SAM_CHALLENGE (-1760647378L) #define KV5M_SAM_KEY (-1760647377L) #define KV5M_ENC_SAM_RESPONSE_ENC (-1760647376L) #define KV5M_ENC_SAM_RESPONSE_ENC_2 (-1760647374L) #define KV5M_SAM_RESPONSE (-1760647373L) #define KV5M_SAM_RESPONSE_2 (-1760647372L) #define KV5M_PREDICTED_SAM_RESPONSE (-1760647371L) #define KV5M_PASSWD_PHRASE_ELEMENT (-1760647370L) #define KV5M_GSS_OID (-1760647369L) #define KV5M_GSS_QUEUE (-1760647368L) #define ERROR_TABLE_BASE_kv5m (-1760647424L) /* for compatibility with older versions... */ #define kv5m_err_base ERROR_TABLE_BASE_kv5m /* * asn1_err.h: * This file is automatically generated; please do not edit it. */ #define ASN1_BAD_TIMEFORMAT (1859794432L) #define ASN1_MISSING_FIELD (1859794433L) #define ASN1_MISPLACED_FIELD (1859794434L) #define ASN1_TYPE_MISMATCH (1859794435L) #define ASN1_OVERFLOW (1859794436L) #define ASN1_OVERRUN (1859794437L) #define ASN1_BAD_ID (1859794438L) #define ASN1_BAD_LENGTH (1859794439L) #define ASN1_BAD_FORMAT (1859794440L) #define ASN1_PARSE_ERROR (1859794441L) #define ASN1_BAD_GMTIME (1859794442L) #define ASN1_MISMATCH_INDEF (1859794443L) #define ASN1_MISSING_EOC (1859794444L) #define ERROR_TABLE_BASE_asn1 (1859794432L) /* for compatibility with older versions... */ #define asn1_err_base ERROR_TABLE_BASE_asn1 #endif /* _KRB5_H */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" void krb5_old_encrypt_length (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t input, size_t *length); krb5_error_code krb5_old_encrypt (krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); krb5_error_code krb5_old_decrypt (krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); #ifndef _KERNEL krb5_error_code krb5int_des_string_to_key (krb5_context context, const struct krb5_enc_provider *enc, const krb5_data *string, const krb5_data *salt, const krb5_data *params, krb5_keyblock *key); #endif /* _KERNEL */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" void krb5_raw_encrypt_length (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, size_t input, size_t *length); krb5_error_code krb5_raw_encrypt (krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); krb5_error_code krb5_raw_decrypt (krb5_context context, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/crypto/md4/rsa-md4.h * * Copyright 1991 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. * * * RSA MD4 header file, with Kerberos/STDC additions. */ #ifndef __KRB5_RSA_MD4_H__ #define __KRB5_RSA_MD4_H__ #ifdef unicos61 #include #endif /* unicos61 */ /* 16 u_char's in the digest */ #define RSA_MD4_CKSUM_LENGTH 16 /* des blocksize is 8, so this works nicely... */ #define OLD_RSA_MD4_DES_CKSUM_LENGTH 16 #define NEW_RSA_MD4_DES_CKSUM_LENGTH 24 #define RSA_MD4_DES_CONFOUND_LENGTH 8 /* ********************************************************************** ** md4.h -- Header file for implementation of MD4 ** ** RSA Data Security, Inc. MD4 Message Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** ********************************************************************** */ /* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD4 Message ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD4 Message Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** ********************************************************************** */ /* Data structure for MD4 (Message Digest) computation */ typedef struct { krb5_ui_4 i[2]; /* number of _bits_ handled mod 2^64 */ krb5_ui_4 buf[4]; /* scratch buffer */ unsigned char in[64]; /* input buffer */ unsigned char digest[16]; /* actual digest after MD4Final call */ } krb5_MD4_CTX; extern void krb5_MD4Init(krb5_MD4_CTX *); extern void krb5_MD4Update(krb5_MD4_CTX *, const unsigned char *, unsigned int); extern void krb5_MD4Final(krb5_MD4_CTX *); /* ********************************************************************** ** End of md4.h ** ******************************* (cut) ******************************** */ #endif /* __KRB5_RSA_MD4_H__ */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/copy_athctr.c * * Copyright 1990,1991 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. * * * krb5_copy_authenticator() */ #include krb5_error_code KRB5_CALLCONV krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto) { krb5_error_code retval; krb5_authenticator *tempto; if (!(tempto = (krb5_authenticator *)MALLOC(sizeof(*tempto)))) return ENOMEM; #ifdef HAVE_C_STRUCTURE_ASSIGNMENT *tempto = *authfrom; #else (void) memcpy(tempto, authfrom, sizeof(krb5_authenticator)); #endif retval = krb5_copy_principal(context, authfrom->client, &tempto->client); if (retval) { krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } if (authfrom->checksum && (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) { krb5_free_principal(context, tempto->client); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } if (authfrom->subkey) { retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey); if (retval) { krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock)); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } } if (authfrom->authorization_data) { retval = krb5_copy_authdata(context, authfrom->authorization_data, &tempto->authorization_data); if (retval) { krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock)); krb5_free_checksum(context, tempto->checksum); krb5_free_principal(context, tempto->client); krb5_free_authdata(context, tempto->authorization_data); krb5_xfree_wrap(tempto, sizeof(*tempto)); return retval; } } *authto = tempto; return 0; } /* * lib/krb5/krb/copy_auth.c * * Copyright 1990 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. * * * krb5_copy_authdata() */ /* * Copyright (c) 2006-2008, Novell, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * The copyright holder's name is not used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "k5-int.h" static krb5_error_code krb5_copy_authdatum(krb5_context context, const krb5_authdata *inad, krb5_authdata **outad) { krb5_authdata *tmpad; if (!(tmpad = (krb5_authdata *)malloc(sizeof(*tmpad)))) return ENOMEM; *tmpad = *inad; if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) { free(tmpad); return ENOMEM; } (void) memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length); *outad = tmpad; return 0; } /* * Copy an authdata array, with fresh allocation. */ krb5_error_code KRB5_CALLCONV krb5_merge_authdata(krb5_context context, krb5_authdata *const *inauthdat1, krb5_authdata * const *inauthdat2, krb5_authdata ***outauthdat) { krb5_error_code retval; krb5_authdata ** tempauthdat; register unsigned int nelems = 0, nelems2 = 0; *outauthdat = NULL; if (!inauthdat1 && !inauthdat2) { *outauthdat = 0; return 0; } if (inauthdat1) while (inauthdat1[nelems]) nelems++; if (inauthdat2) while (inauthdat2[nelems2]) nelems2++; /* one more for a null terminated list */ if (!(tempauthdat = (krb5_authdata **) calloc(nelems+nelems2+1, sizeof(*tempauthdat)))) return ENOMEM; if (inauthdat1) { for (nelems = 0; inauthdat1[nelems]; nelems++) { retval = krb5_copy_authdatum(context, inauthdat1[nelems], &tempauthdat[nelems]); if (retval) { krb5_free_authdata(context, tempauthdat); return retval; } } } if (inauthdat2) { for (nelems2 = 0; inauthdat2[nelems2]; nelems2++) { retval = krb5_copy_authdatum(context, inauthdat2[nelems2], &tempauthdat[nelems++]); if (retval) { krb5_free_authdata(context, tempauthdat); return retval; } } } *outauthdat = tempauthdat; return 0; } krb5_error_code KRB5_CALLCONV krb5_copy_authdata(krb5_context context, krb5_authdata *const *in_authdat, krb5_authdata ***out) { return krb5_merge_authdata(context, in_authdat, NULL, out); } krb5_error_code KRB5_CALLCONV krb5_decode_authdata_container(krb5_context context, krb5_authdatatype type, const krb5_authdata *container, krb5_authdata ***authdata) { krb5_error_code code; krb5_data data; *authdata = NULL; if ((container->ad_type & AD_TYPE_FIELD_TYPE_MASK) != type) return EINVAL; data.length = container->length; data.data = (char *)container->contents; code = decode_krb5_authdata(&data, authdata); if (code) return code; return 0; } krb5_error_code KRB5_CALLCONV krb5_encode_authdata_container(krb5_context context, krb5_authdatatype type, krb5_authdata *const*authdata, krb5_authdata ***container) { krb5_error_code code; krb5_data *data; krb5_authdata ad_datum; krb5_authdata *ad_data[2]; *container = NULL; code = encode_krb5_authdata((krb5_authdata * const *)authdata, &data); if (code) return code; ad_datum.ad_type = type & AD_TYPE_FIELD_TYPE_MASK; ad_datum.length = data->length; ad_datum.contents = (unsigned char *)data->data; ad_data[0] = &ad_datum; ad_data[1] = NULL; code = krb5_copy_authdata(context, ad_data, container); krb5_free_data(context, data); return code; } struct find_authdata_context { krb5_authdata **out; size_t space; size_t length; }; static krb5_error_code grow_find_authdata (krb5_context context, struct find_authdata_context *fctx, krb5_authdata *elem) { krb5_error_code retval = 0; if (fctx->length == fctx->space) { krb5_authdata **new; if (fctx->space >= 256) { krb5_set_error_message(context, ERANGE, "More than 256 authdata matched a query"); return ERANGE; } new = realloc(fctx->out, sizeof (krb5_authdata *)*(2*fctx->space+1)); if (new == NULL) return ENOMEM; fctx->out = new; fctx->space *=2; } fctx->out[fctx->length+1] = NULL; retval = krb5_copy_authdatum(context, elem, &fctx->out[fctx->length]); if (retval == 0) fctx->length++; return retval; } static krb5_error_code find_authdata_1 (krb5_context context, krb5_authdata *const *in_authdat, krb5_authdatatype ad_type, struct find_authdata_context *fctx) { int i = 0; krb5_error_code retval=0; for (i = 0; in_authdat[i]; i++) { krb5_authdata *ad = in_authdat[i]; if (ad->ad_type == ad_type && retval ==0) retval = grow_find_authdata(context, fctx, ad); else switch (ad->ad_type) { krb5_authdata **decoded_container; case KRB5_AUTHDATA_IF_RELEVANT: if (retval == 0) retval = krb5_decode_authdata_container( context, ad->ad_type, ad, &decoded_container); if (retval == 0) { retval = find_authdata_1(context, decoded_container, ad_type, fctx); krb5_free_authdata(context, decoded_container); } break; default: break; } } return retval; } krb5_error_code krb5int_find_authdata (krb5_context context, krb5_authdata *const * ticket_authdata, krb5_authdata * const *ap_req_authdata, krb5_authdatatype ad_type, krb5_authdata ***results) { krb5_error_code retval = 0; struct find_authdata_context fctx; fctx.length = 0; fctx.space = 2; fctx.out = calloc(fctx.space+1, sizeof (krb5_authdata *)); *results = NULL; if (fctx.out == NULL) return ENOMEM; if (ticket_authdata) retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx); if ((retval==0) && ap_req_authdata) retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx); if ((retval== 0) && fctx.length) *results = fctx.out; else krb5_free_authdata(context, fctx.out); return retval; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/copy_cksum.c * * Copyright 1990 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. * * * krb5_copy_checksum() */ #include "k5-int.h" /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom, krb5_checksum **ckto) { krb5_checksum *tempto; if (!(tempto = (krb5_checksum *)MALLOC(sizeof(*tempto)))) return ENOMEM; *tempto = *ckfrom; if (!(tempto->contents = (krb5_octet *)MALLOC(tempto->length))) { krb5_xfree(tempto); return ENOMEM; } (void) memcpy((char *) tempto->contents, (char *) ckfrom->contents, ckfrom->length); *ckto = tempto; return 0; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/copy_key.c * * Copyright 1990,1991 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. * * * krb5_copy_keyblock() */ #include "k5-int.h" /* * krb5_copy_keyblock_data * * Utility for copying keyblock data structures safely. * This assumes that the necessary storage areas are * already allocated. */ krb5_error_code krb5_copy_keyblock_data(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to) { krb5_error_code ret = 0; /* If nothing to copy, return no error */ if (from == NULL || to == NULL) return (0); if ((to->contents == NULL || from->contents == NULL) && from->length > 0) return (ENOMEM); to->magic = from->magic; to->enctype = from->enctype; to->length = from->length; to->dk_list = NULL; if (from->length > 0) (void) memcpy(to->contents, from->contents, from->length); #ifdef _KERNEL to->kef_mt = from->kef_mt; to->kef_key.ck_data = NULL; to->key_tmpl = NULL; if ((ret = init_key_kef(context->kef_cipher_mt, to))) { return (ret); } #else /* * Don't copy or try to initialize crypto framework * data. This data gets initialized the first time it is * used. */ to->hKey = CK_INVALID_HANDLE; #endif /* _KERNEL */ return (ret); } /* * Copy a keyblock, including alloc'ed storage. */ /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_copy_keyblock(context, from, to) krb5_context context; const krb5_keyblock *from; krb5_keyblock **to; { krb5_keyblock *new_key; krb5_error_code ret = 0; if (!(new_key = (krb5_keyblock *) MALLOC(sizeof(krb5_keyblock)))) return (ENOMEM); if (!(new_key->contents = (krb5_octet *)MALLOC(from->length))) { FREE(new_key, sizeof(krb5_keyblock)); return (ENOMEM); } ret = krb5_copy_keyblock_data(context, from, new_key); if (ret) { krb5_free_keyblock(context, new_key); return (ret); } *to = new_key; return (ret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/copy_princ.c * * Copyright 1990 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. * * * krb5_copy_principal() */ #include "k5-int.h" /* * Copy a principal structure, with fresh allocation. */ /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc) { register krb5_principal tempprinc; register int i, nelems; tempprinc = (krb5_principal)MALLOC(sizeof(krb5_principal_data)); if (tempprinc == 0) return ENOMEM; *tempprinc = *inprinc; nelems = (int) krb5_princ_size(context, inprinc); tempprinc->data = MALLOC(nelems * sizeof(krb5_data)); if (tempprinc->data == 0) { FREE((char *)tempprinc, sizeof(krb5_principal_data)); return ENOMEM; } for (i = 0; i < nelems; i++) { unsigned int len = krb5_princ_component(context, inprinc, i)->length; krb5_princ_component(context, tempprinc, i)->length = len; /* * Allocate one extra byte for trailing zero byte so string ops * can be used on the components. */ if (len && ((krb5_princ_component(context, tempprinc, i)->data = MALLOC(len + 1)) == 0)) { while (--i >= 0) FREE(krb5_princ_component(context, tempprinc, i)->data, krb5_princ_component(context, inprinc, i)->length + 1); FREE (tempprinc->data, nelems * sizeof(krb5_data)); FREE (tempprinc,sizeof(krb5_principal_data)); return ENOMEM; } if (len) (void) memcpy(krb5_princ_component(context, tempprinc, i)->data, krb5_princ_component(context, inprinc, i)->data, len); else krb5_princ_component(context, tempprinc, i)->data = 0; } tempprinc->realm.length = inprinc->realm.length; /* * Allocate one extra byte for the realm name string terminator. The * realm and principle component strings alway leave a null byte after * 'length' bytes that needs to be malloc/freed. */ tempprinc->realm.data = MALLOC(tempprinc->realm.length + 1); if (!tempprinc->realm.data) { for (i = 0; i < nelems; i++) FREE(krb5_princ_component(context, tempprinc, i)->data, krb5_princ_component(context, inprinc, i)->length + 1); FREE(tempprinc->data, nelems * sizeof(krb5_data)); FREE(tempprinc, sizeof(krb5_principal_data)); return ENOMEM; } memcpy(tempprinc->realm.data, inprinc->realm.data, inprinc->realm.length); tempprinc->realm.data[tempprinc->realm.length] = 0; *outprinc = tempprinc; return 0; } /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/init_ctx.c * * Copyright 1994,1999,2000, 2002, 2003 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. * * krb5_init_contex() */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "k5-int.h" /* * Solaris Kerberos: the code related to EF/pkcs11 and fork safety are mods Sun * has made to the MIT code. */ #ifndef _KERNEL #include pid_t __krb5_current_pid; /* fork safety: contains the current process ID */ #endif #ifndef _KERNEL #include #endif /* The des-mdX entries are last for now, because it's easy to configure KDCs to issue TGTs with des-mdX keys and then not accept them. This'll be fixed, but for better compatibility, let's prefer des-crc for now. */ /* * Solaris Kerberos: * Added arcfour-hmac-md5-exp as default enc type. * Changed des3-hmac-sha1 to des3-cbc-sha1-kd, as specified in RFC3961. */ #define DEFAULT_ETYPE_LIST \ "aes256-cts-hmac-sha1-96 " \ "aes128-cts-hmac-sha1-96 " \ "des3-cbc-sha1-kd " \ "arcfour-hmac-md5 " \ "arcfour-hmac-md5-exp " \ "des-cbc-md5 " \ "des-cbc-crc" /* The only functions that are needed from this file when in kernel are * krb5_init_context and krb5_free_context. * In krb5_init_context we need only os_init_context since we don'it need the * profile info unless we do init/accept in kernel. Currently only mport, * delete , sign/verify, wrap/unwrap routines are ported to the kernel. */ #if (defined(_WIN32)) extern krb5_error_code krb5_vercheck(); extern void krb5_win_ccdll_load(krb5_context context); #endif static krb5_error_code init_common (krb5_context *, krb5_boolean, krb5_boolean); krb5_error_code KRB5_CALLCONV krb5_init_context(krb5_context *context) { return init_common (context, FALSE, FALSE); } krb5_error_code KRB5_CALLCONV krb5_init_secure_context(krb5_context *context) { #if 0 /* Solaris Kerberos */ /* This is to make gcc -Wall happy */ if(0) krb5_brand[0] = krb5_brand[0]; #endif return init_common (context, TRUE, FALSE); } #ifndef _KERNEL krb5_error_code krb5int_init_context_kdc(krb5_context *context) { return init_common (context, FALSE, TRUE); } /* Solaris Kerberos */ krb5_error_code krb5_open_pkcs11_session(CK_SESSION_HANDLE *hSession) { krb5_error_code retval = 0; CK_RV rv; CK_SLOT_ID_PTR slotlist = NULL_PTR; CK_ULONG slotcount; CK_ULONG i; /* List of all Slots */ rv = C_GetSlotList(FALSE, NULL_PTR, &slotcount); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x.", rv); retval = PKCS_ERR; goto cleanup; } if (slotcount == 0) { KRB5_LOG0(KRB5_ERR, "No slot is found in PKCS11."); retval = PKCS_ERR; goto cleanup; } slotlist = (CK_SLOT_ID_PTR)malloc(slotcount * sizeof(CK_SLOT_ID)); if (slotlist == NULL) { KRB5_LOG0(KRB5_ERR, "malloc failed for slotcount."); retval = PKCS_ERR; goto cleanup; } rv = C_GetSlotList(FALSE, slotlist, &slotcount); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x", rv); retval = PKCS_ERR; goto cleanup; } for (i = 0; i < slotcount; i++) { if (slot_supports_krb5(slotlist + i)) break; } if (i == slotcount){ KRB5_LOG0(KRB5_ERR, "Could not find slot which supports " "Kerberos"); retval = PKCS_ERR; goto cleanup; } rv = C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, hSession); if (rv != CKR_OK) { retval = PKCS_ERR; } cleanup: if (slotlist != NULL) free(slotlist); return(retval); } /* * krb5_reinit_ef_handle() * * deal with fork safety issue regarding the krb ctx and the pkcs11 hSession * field. This function is called if it is determined that the krb ctx hSession * is being accessed in a child process after a fork(). This function * re-initilizes the pkcs11 session and returns the session handle. */ CK_SESSION_HANDLE krb5_reinit_ef_handle(krb5_context ctx) { ctx->cryptoki_initialized = FALSE; if (krb5_init_ef_handle(ctx) != 0) { /* * krb5_free_ef_handle() not needed here -- we assume that an equivalent * of C_Finalize() was done in the child-side of the fork(), so all EF * resources in this context will be invalid. */ return(CK_INVALID_HANDLE); } /* reset the ctx pid since we're in a new process (child) */ ctx->pid = __krb5_current_pid; /* If the RC4 handles were initialized, reset them here */ if (ctx->arcfour_ctx.initialized) { krb5_error_code ret; ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.eSession); if (ret) { ctx->arcfour_ctx.initialized = 0; ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE; C_CloseSession(ctx->hSession); ctx->hSession = CK_INVALID_HANDLE; } ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.dSession); if (ret) { ctx->arcfour_ctx.initialized = 0; ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE; ctx->arcfour_ctx.dSession = CK_INVALID_HANDLE; C_CloseSession(ctx->hSession); ctx->hSession = CK_INVALID_HANDLE; } } /* * It is safe for this function to access ctx->hSession directly. Do * NOT use the krb_ctx_hSession() here. */ return(ctx->hSession); } /* * krb5_pthread_atfork_child_handler() sets a global that indicates the current * PID. This is an optimization to keep getpid() from being called a zillion * times. */ void krb5_pthread_atfork_child_handler() { /* * __krb5_current_pid should always be set to current process ID, see the * definition of krb_ctx_hSession() for more info */ __krb5_current_pid = getpid(); } /* * krb5_ld_init() contains code that will be executed at load time (via the * ld -zinitarray directive). */ void krb5_ld_init() { /* * fork safety: __krb5_current_pid should always be set to current process * ID, see the definition of krb_ctx_hSession() for more info */ __krb5_current_pid = getpid(); /* * The child handler below will help reduce the number of times getpid() is * called by updating a global PID var. with the current PID whenever a fork * occurrs. */ (void) pthread_atfork(NULL, NULL, krb5_pthread_atfork_child_handler); } #endif /* !_KERNEL */ krb5_error_code krb5_init_ef_handle(krb5_context ctx) { krb5_error_code retval = 0; #ifndef _KERNEL CK_RV rv = C_Initialize(NULL_PTR); if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { KRB5_LOG(KRB5_ERR, "C_Initialize failed with 0x%x.", rv); return (PKCS_ERR); } /* * It is safe for this function to access ctx->hSession directly. Do * NOT use the krb_ctx_hSession() here. */ retval = krb5_open_pkcs11_session(&ctx->hSession); if (retval != 0) return (retval); ctx->cryptoki_initialized = TRUE; #else /* ! _KERNEL */ ctx->kef_cipher_mt = CRYPTO_MECH_INVALID; ctx->kef_hash_mt = CRYPTO_MECH_INVALID; ctx->kef_cksum_mt = CRYPTO_MECH_INVALID; setup_kef_keytypes(); setup_kef_cksumtypes(); #endif /* ! _KERNEL */ return(retval); } #ifndef _KERNEL krb5_error_code krb5_free_ef_handle(krb5_context ctx) { /* * fork safety: Don't free any PKCS state if we've forked since * allocating the pkcs handles. */ if (ctx->cryptoki_initialized == TRUE && ctx->pid == __krb5_current_pid) { /* * It is safe for this function to access ctx->hSession * directly. Do NOT use the krb_ctx_hSession() here. */ if (ctx->hSession) { C_CloseSession(ctx->hSession); ctx->hSession = 0; } if (ctx->arcfour_ctx.dKey) { C_DestroyObject(ctx->arcfour_ctx.dSession, ctx->arcfour_ctx.dKey); ctx->arcfour_ctx.dKey = 0; } if (ctx->arcfour_ctx.eKey) { C_DestroyObject(ctx->arcfour_ctx.eSession, ctx->arcfour_ctx.eKey); ctx->arcfour_ctx.eKey = 0; } if (ctx->arcfour_ctx.eSession) { C_CloseSession(ctx->arcfour_ctx.eSession); ctx->arcfour_ctx.eSession = 0; } if (ctx->arcfour_ctx.dSession) { C_CloseSession(ctx->arcfour_ctx.dSession); ctx->arcfour_ctx.eSession = 0; } ctx->arcfour_ctx.initialized = 0; ctx->cryptoki_initialized = FALSE; } return(0); } #endif /* !_KERNEL */ static krb5_error_code init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc) { krb5_context ctx = 0; krb5_error_code retval; #ifndef _KERNEL struct { krb5_int32 now, now_usec; long pid; } seed_data; krb5_data seed; int tmp; /* Solaris Kerberos */ #if 0 /* Verify some assumptions. If the assumptions hold and the compiler is optimizing, this should result in no code being executed. If we're guessing "unsigned long long" instead of using uint64_t, the possibility does exist that we're wrong. */ { krb5_ui_8 i64; assert(sizeof(i64) == 8); i64 = 0, i64--, i64 >>= 62; assert(i64 == 3); i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1; assert(i64 != 0); i64 <<= 1; assert(i64 == 0); } #endif retval = krb5int_initialize_library(); if (retval) return retval; #endif #if (defined(_WIN32)) /* * Load the krbcc32.dll if necessary. We do this here so that * we know to use API: later on during initialization. * The context being NULL is ok. */ krb5_win_ccdll_load(ctx); /* * krb5_vercheck() is defined in win_glue.c, and this is * where we handle the timebomb and version server checks. */ retval = krb5_vercheck(); if (retval) return retval; #endif *context = 0; ctx = MALLOC(sizeof(struct _krb5_context)); if (!ctx) return ENOMEM; (void) memset(ctx, 0, sizeof(struct _krb5_context)); ctx->magic = KV5M_CONTEXT; ctx->profile_secure = secure; if ((retval = krb5_os_init_context(ctx, kdc))) goto cleanup; /* * Initialize the EF handle, its needed before doing * the random seed. */ if ((retval = krb5_init_ef_handle(ctx))) goto cleanup; #ifndef _KERNEL /* fork safety: set pid to current process ID for later checking */ ctx->pid = __krb5_current_pid; /* Set the default encryption types, possible defined in krb5/conf */ if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL))) goto cleanup; if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL))) goto cleanup; if (ctx->tgs_ktype_count != 0) { ctx->conf_tgs_ktypes = MALLOC(ctx->tgs_ktype_count * sizeof(krb5_enctype)); if (ctx->conf_tgs_ktypes == NULL) goto cleanup; (void) memcpy(ctx->conf_tgs_ktypes, ctx->tgs_ktypes, sizeof(krb5_enctype) * ctx->tgs_ktype_count); } ctx->conf_tgs_ktypes_count = ctx->tgs_ktype_count; /* initialize the prng (not well, but passable) */ if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec))) goto cleanup; seed_data.pid = getpid (); seed.length = sizeof(seed_data); seed.data = (char *) &seed_data; if ((retval = krb5_c_random_seed(ctx, &seed))) /* * Solaris Kerberos: we use /dev/urandom, which is * automatically seeded, so its OK if this fails. */ retval = 0; ctx->default_realm = 0; profile_get_integer(ctx->profile, "libdefaults", "clockskew", 0, 5 * 60, &tmp); ctx->clockskew = tmp; #if 0 /* Default ticket lifetime is currently not supported */ profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime", 0, 10 * 60 * 60, &tmp); ctx->tkt_lifetime = tmp; #endif /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2) */ /* DCE add kdc_req_checksum_type = 2 to krb5.conf */ profile_get_integer(ctx->profile, "libdefaults", "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, &tmp); ctx->kdc_req_sumtype = tmp; profile_get_integer(ctx->profile, "libdefaults", "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, &tmp); ctx->default_ap_req_sumtype = tmp; profile_get_integer(ctx->profile, "libdefaults", "safe_checksum_type", 0, CKSUMTYPE_RSA_MD5_DES, &tmp); ctx->default_safe_sumtype = tmp; profile_get_integer(ctx->profile, "libdefaults", "kdc_default_options", 0, KDC_OPT_RENEWABLE_OK, &tmp); ctx->kdc_default_options = tmp; #define DEFAULT_KDC_TIMESYNC 1 profile_get_integer(ctx->profile, "libdefaults", "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC, &tmp); ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0; /* * We use a default file credentials cache of 3. See * lib/krb5/krb/ccache/file/fcc.h for a description of the * credentials cache types. * * Note: DCE 1.0.3a only supports a cache type of 1 * DCE 1.1 supports a cache type of 2. */ #define DEFAULT_CCACHE_TYPE 4 profile_get_integer(ctx->profile, "libdefaults", "ccache_type", 0, DEFAULT_CCACHE_TYPE, &tmp); ctx->fcc_default_format = tmp + 0x0500; ctx->scc_default_format = tmp + 0x0500; ctx->prompt_types = 0; ctx->use_conf_ktypes = 0; ctx->udp_pref_limit = -1; #endif /* !_KERNEL */ *context = ctx; return 0; cleanup: krb5_free_context(ctx); return retval; } void KRB5_CALLCONV krb5_free_context(krb5_context ctx) { KRB5_LOG0(KRB5_INFO,"krb5_free_context() start"); #ifndef _KERNEL krb5_free_ef_handle(ctx); if (ctx->conf_tgs_ktypes) { FREE(ctx->conf_tgs_ktypes, sizeof(krb5_enctype) *(ctx->conf_tgs_ktypes_count)); ctx->conf_tgs_ktypes = 0; ctx->conf_tgs_ktypes_count = 0; } krb5_clear_error_message(ctx); #endif krb5_os_free_context(ctx); if (ctx->in_tkt_ktypes) { FREE(ctx->in_tkt_ktypes, sizeof(krb5_enctype) *(ctx->in_tkt_ktype_count+1) ); ctx->in_tkt_ktypes = 0; } if (ctx->tgs_ktypes) { FREE(ctx->tgs_ktypes, sizeof(krb5_enctype) *(ctx->tgs_ktype_count+1)); ctx->tgs_ktypes = 0; } if (ctx->default_realm) { FREE(ctx->default_realm, strlen(ctx->default_realm) + 1); ctx->default_realm = 0; } if (ctx->ser_ctx_count && ctx->ser_ctx) { FREE(ctx->ser_ctx,sizeof(krb5_ser_entry) * (ctx->ser_ctx_count) ); ctx->ser_ctx = 0; ctx->ser_ctx_count = 0; } ctx->magic = 0; FREE(ctx, sizeof(struct _krb5_context)); } #ifndef _KERNEL /* * Set the desired default ktypes, making sure they are valid. */ krb5_error_code krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes) { krb5_enctype * new_ktypes; int i; if (ktypes) { for (i = 0; ktypes[i]; i++) { if (!krb5_c_valid_enctype(ktypes[i])) return KRB5_PROG_ETYPE_NOSUPP; } /* Now copy the default ktypes into the context pointer */ if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); else return ENOMEM; } else { i = 0; new_ktypes = 0; } if (context->in_tkt_ktypes) free(context->in_tkt_ktypes); context->in_tkt_ktypes = new_ktypes; context->in_tkt_ktype_count = i; return 0; } static krb5_error_code get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr, unsigned int ctx_count, krb5_enctype *ctx_list) { krb5_enctype *old_ktypes = NULL; if (ctx_count) { /* application-set defaults */ if ((old_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * (ctx_count + 1)))) { (void) memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count); old_ktypes[ctx_count] = 0; } else { return ENOMEM; } } else { /* XXX - For now, we only support libdefaults Perhaps this should be extended to allow for per-host / per-realm session key types. */ char *retval = NULL; char *sp, *ep; int j, checked_enctypes, count; krb5_error_code code; code = profile_get_string(context->profile, "libdefaults", profstr, NULL, DEFAULT_ETYPE_LIST, &retval); if (code) return code; if (!retval) /* SUNW14resync - just in case */ return PROF_EINVAL; /* XXX */ count = 0; sp = retval; while (*sp) { for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++) ; if (*ep) { *ep++ = '\0'; while (isspace((int) (*ep)) || *ep == ',') *ep++ = '\0'; } count++; sp = ep; } if ((old_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) == (krb5_enctype *) NULL) return ENOMEM; sp = retval; j = checked_enctypes = 0; /*CONSTCOND*/ while (TRUE) { checked_enctypes++; if (krb5_string_to_enctype(sp, &old_ktypes[j])) old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; /* * If 'null' has been specified as a tkt_enctype in * krb5.conf, we need to assign an ENCTYPE_UNKNOWN * value to the corresponding old_ktypes[j] entry. */ if (old_ktypes[j] == (unsigned int)ENCTYPE_NULL) old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; /* Only include known/valid enctypes in the final list */ if (old_ktypes[j] != ENCTYPE_UNKNOWN) { j++; } /* If we checked all the enctypes, we are done */ if (checked_enctypes == count) { break; } /* skip to next token */ while (*sp) sp++; while (! *sp) sp++; } old_ktypes[j] = (krb5_enctype) 0; profile_release_string(retval); } if (old_ktypes[0] == 0) { free (old_ktypes); *ktypes = 0; return KRB5_CONFIG_ETYPE_NOSUPP; } *ktypes = old_ktypes; return 0; } krb5_error_code krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes) { return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes", context->in_tkt_ktype_count, context->in_tkt_ktypes)); } krb5_error_code KRB5_CALLCONV krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes) { krb5_enctype * new_ktypes; int i; if (ktypes) { for (i = 0; ktypes[i]; i++) { if (!krb5_c_valid_enctype(ktypes[i])) return KRB5_PROG_ETYPE_NOSUPP; } /* Now copy the default ktypes into the context pointer */ if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); else return ENOMEM; } else { i = 0; new_ktypes = (krb5_enctype *)NULL; } if (context->tgs_ktypes) krb5_free_ktypes(context, context->tgs_ktypes); context->tgs_ktypes = new_ktypes; context->tgs_ktype_count = i; return 0; } krb5_error_code krb5_set_default_tgs_ktypes (krb5_context context, const krb5_enctype *etypes) { return (krb5_set_default_tgs_enctypes (context, etypes)); } /*ARGSUSED*/ void KRB5_CALLCONV krb5_free_ktypes (krb5_context context, krb5_enctype *val) { free (val); } /*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes) { if (context->use_conf_ktypes) /* This one is set *only* by reading the config file; it's not set by the application. */ return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", context->conf_tgs_ktypes_count, context->conf_tgs_ktypes)); else return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", context->tgs_ktype_count, context->tgs_ktypes)); } krb5_error_code krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes) { return(get_profile_etype_list(context, ktypes, "permitted_enctypes", context->tgs_ktype_count, context->tgs_ktypes)); } krb5_boolean krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype) { krb5_enctype *list, *ptr; krb5_boolean ret; if (krb5_get_permitted_enctypes(context, &list)) return(0); ret = 0; for (ptr = list; *ptr; ptr++) if (*ptr == etype) ret = 1; krb5_free_ktypes (context, list); return(ret); } static krb5_error_code copy_ktypes(krb5_context ctx, unsigned int nktypes, krb5_enctype *oldktypes, krb5_enctype **newktypes) { unsigned int i; *newktypes = NULL; if (!nktypes) return 0; *newktypes = MALLOC(nktypes * sizeof(krb5_enctype)); if (*newktypes == NULL) return ENOMEM; for (i = 0; i < nktypes; i++) (*newktypes)[i] = oldktypes[i]; return 0; } krb5_error_code KRB5_CALLCONV krb5_copy_context(krb5_context ctx, krb5_context *nctx_out) { krb5_error_code ret; krb5_context nctx; *nctx_out = NULL; if (ctx == NULL) return EINVAL; /* XXX */ nctx = MALLOC(sizeof(*nctx)); if (nctx == NULL) return ENOMEM; *nctx = *ctx; nctx->in_tkt_ktypes = NULL; nctx->in_tkt_ktype_count = 0; nctx->tgs_ktypes = NULL; nctx->tgs_ktype_count = 0; nctx->default_realm = NULL; nctx->profile = NULL; nctx->db_context = NULL; nctx->ser_ctx_count = 0; nctx->ser_ctx = NULL; nctx->prompt_types = NULL; nctx->os_context->default_ccname = NULL; memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins)); nctx->preauth_context = NULL; memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins)); nctx->vtbl = NULL; nctx->locate_fptrs = NULL; memset(&nctx->err, 0, sizeof(nctx->err)); ret = copy_ktypes(nctx, ctx->in_tkt_ktype_count, ctx->in_tkt_ktypes, &nctx->in_tkt_ktypes); if (ret) goto errout; nctx->in_tkt_ktype_count = ctx->in_tkt_ktype_count; ret = copy_ktypes(nctx, ctx->tgs_ktype_count, ctx->tgs_ktypes, &nctx->in_tkt_ktypes); if (ret) goto errout; nctx->tgs_ktype_count = ctx->tgs_ktype_count; if (ctx->os_context->default_ccname != NULL) { nctx->os_context->default_ccname = strdup(ctx->os_context->default_ccname); if (nctx->os_context->default_ccname == NULL) { ret = ENOMEM; goto errout; } } ret = krb5_get_profile(ctx, &nctx->profile); if (ret) goto errout; errout: if (ret) { krb5_free_context(nctx); } else { *nctx_out = nctx; } return ret; } #endif /* !KERNEL */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 1990-1998 by the Massachusetts Institute of Technology. * * 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. * * * krb5_free_address() */ #include "k5-int.h" static void cleanup_dk_list(krb5_context, krb5_keyblock *); /* ARGSUSED */ void KRB5_CALLCONV krb5_free_address(krb5_context context, krb5_address *val) { if (val->contents) krb5_xfree_wrap(val->contents, val->length); krb5_xfree_wrap(val, sizeof(krb5_address)); } #ifndef _KERNEL void KRB5_CALLCONV krb5_free_addresses(krb5_context context, krb5_address **val) { register krb5_address **temp; for (temp = val; *temp; temp++) { if ((*temp)->contents) krb5_xfree((*temp)->contents); krb5_xfree(*temp); } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_ap_rep(krb5_context context, register krb5_ap_rep *val) { if (val->enc_part.ciphertext.data) { krb5_xfree(val->enc_part.ciphertext.data); val->enc_part.ciphertext.data = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_ap_req(krb5_context context, register krb5_ap_req *val) { if (val->ticket) { krb5_free_ticket(context, val->ticket); val->ticket = 0; } if (val->authenticator.ciphertext.data) { krb5_xfree(val->authenticator.ciphertext.data); val->authenticator.ciphertext.data = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val) { if (val->subkey) krb5_free_keyblock(context, val->subkey); krb5_xfree(val); } #endif /* !_KERNEL */ void KRB5_CALLCONV krb5_free_authenticator_contents(krb5_context context, krb5_authenticator *val) { if (val->checksum) { krb5_free_checksum(context, val->checksum); val->checksum = 0; } if (val->client) { krb5_free_principal(context, val->client); val->client = 0; } if (val->subkey) { krb5_free_keyblock(context, val->subkey); val->subkey = 0; } if (val->authorization_data) { krb5_free_authdata(context, val->authorization_data); val->authorization_data = 0; } } /* ARGSUSED */ void KRB5_CALLCONV krb5_free_authdata(krb5_context context, krb5_authdata **val) { register krb5_authdata **temp; for (temp = val; *temp; temp++) { if ((*temp)->contents) krb5_xfree_wrap((*temp)->contents, (*temp)->length); krb5_xfree_wrap(*temp, sizeof(krb5_authdata)); } /* Note val points to an array of pointers and (++temp - val) is # of bytes * in that array. */ krb5_xfree_wrap(val, (++temp - val)); } void KRB5_CALLCONV krb5_free_authenticator(krb5_context context, krb5_authenticator *val) { krb5_free_authenticator_contents(context, val); krb5_xfree_wrap(val, sizeof(krb5_authenticator)); } void KRB5_CALLCONV krb5_free_checksum(krb5_context context, register krb5_checksum *val) { krb5_free_checksum_contents(context, val); krb5_xfree_wrap(val, sizeof(krb5_checksum)); } /* ARGSUSED */ void KRB5_CALLCONV krb5_free_checksum_contents(krb5_context context, register krb5_checksum *val) { if (val->contents) { krb5_xfree_wrap(val->contents, val->length); val->length = 0; val->contents = 0; } } #ifndef _KERNEL void KRB5_CALLCONV krb5_free_cred(krb5_context context, register krb5_cred *val) { if (val->tickets) { krb5_free_tickets(context, val->tickets); val->tickets = 0; } if (val->enc_part.ciphertext.data) { krb5_xfree(val->enc_part.ciphertext.data); val->enc_part.ciphertext.data = 0; } krb5_xfree(val); } /* * krb5_free_cred_contents zeros out the session key, and then frees * the credentials structures */ void KRB5_CALLCONV krb5_free_cred_contents(krb5_context context, krb5_creds *val) { if (val->client) { krb5_free_principal(context, val->client); val->client = 0; } if (val->server) { krb5_free_principal(context, val->server); val->server = 0; } krb5_free_keyblock_contents(context, &val->keyblock); if (val->ticket.data) { krb5_xfree(val->ticket.data); val->ticket.data = 0; } if (val->second_ticket.data) { krb5_xfree(val->second_ticket.data); val->second_ticket.data = 0; } if (val->addresses) { krb5_free_addresses(context, val->addresses); val->addresses = 0; } if (val->authdata) { krb5_free_authdata(context, val->authdata); val->authdata = 0; } } void KRB5_CALLCONV krb5_free_cred_enc_part(krb5_context context, register krb5_cred_enc_part *val) { register krb5_cred_info **temp; if (val->r_address) { krb5_free_address(context, val->r_address); val->r_address = 0; } if (val->s_address) { krb5_free_address(context, val->s_address); val->s_address = 0; } if (val->ticket_info) { for (temp = val->ticket_info; *temp; temp++) { if ((*temp)->session) krb5_free_keyblock(context, (*temp)->session); if ((*temp)->client) krb5_free_principal(context, (*temp)->client); if ((*temp)->server) krb5_free_principal(context, (*temp)->server); if ((*temp)->caddrs) krb5_free_addresses(context, (*temp)->caddrs); krb5_xfree((*temp)); } krb5_xfree(val->ticket_info); val->ticket_info = 0; } } void KRB5_CALLCONV krb5_free_creds(krb5_context context, krb5_creds *val) { krb5_free_cred_contents(context, val); krb5_xfree(val); } /* ARGSUSED */ void KRB5_CALLCONV krb5_free_data(krb5_context context, krb5_data *val) { if (val->data) { krb5_xfree(val->data); val->data = 0; } krb5_xfree(val); } #endif /* !_KERNEL */ /* ARGSUSED */ void KRB5_CALLCONV krb5_free_data_contents(krb5_context context, krb5_data *val) { if (val->data) { krb5_xfree_wrap(val->data, val->length); val->length = 0; val->data = 0; } } #ifndef _KERNEL void krb5_free_etype_info(krb5_context context, krb5_etype_info info) { int i; for(i=0; info[i] != NULL; i++) { if (info[i]->salt) free(info[i]->salt); krb5_free_data_contents(context, &info[i]->s2kparams); free(info[i]); } free(info); } void KRB5_CALLCONV krb5_free_enc_kdc_rep_part(krb5_context context, register krb5_enc_kdc_rep_part *val) { if (val->session) krb5_free_keyblock(context, val->session); if (val->last_req) krb5_free_last_req(context, val->last_req); if (val->server) krb5_free_principal(context, val->server); if (val->caddrs) krb5_free_addresses(context, val->caddrs); krb5_xfree(val); } void KRB5_CALLCONV krb5_free_enc_tkt_part(krb5_context context, krb5_enc_tkt_part *val) { if (val->session) { krb5_free_keyblock(context, val->session); val->session = 0; } if (val->client) krb5_free_principal(context, val->client); if (val->transited.tr_contents.data) { krb5_xfree(val->transited.tr_contents.data); val->transited.tr_contents.data = 0; } if (val->caddrs) krb5_free_addresses(context, val->caddrs); if (val->authorization_data) { krb5_free_authdata(context, val->authorization_data); val->authorization_data = 0; } krb5_xfree(val); } #endif /* !_KERNEL */ void KRB5_CALLCONV krb5_free_error(krb5_context context, register krb5_error *val) { if (val->client) krb5_free_principal(context, val->client); if (val->server) krb5_free_principal(context, val->server); if (val->text.data) krb5_xfree_wrap(val->text.data, val->text.length); if (val->e_data.data) krb5_xfree_wrap(val->e_data.data, val->e_data.length); krb5_xfree_wrap(val, sizeof (krb5_error)); } #ifndef _KERNEL void KRB5_CALLCONV krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *val) { if (val->padata) { krb5_free_pa_data(context, val->padata); val->padata = 0; } if (val->client) { krb5_free_principal(context, val->client); val->client = 0; } if (val->ticket) { krb5_free_ticket(context, val->ticket); val->ticket = 0; } if (val->enc_part.ciphertext.data) { krb5_xfree(val->enc_part.ciphertext.data); val->enc_part.ciphertext.data = 0; } if (val->enc_part2) { krb5_free_enc_kdc_rep_part(context, val->enc_part2); val->enc_part2 = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_kdc_req(krb5_context context, krb5_kdc_req *val) { if (val->padata) { krb5_free_pa_data(context, val->padata); val->padata = 0; } if (val->client) { krb5_free_principal(context, val->client); val->client = 0; } if (val->server) { krb5_free_principal(context, val->server); val->server = 0; } if (val->ktype) { krb5_xfree(val->ktype); val->ktype = 0; } if (val->addresses) { krb5_free_addresses(context, val->addresses); val->addresses = 0; } if (val->authorization_data.ciphertext.data) { krb5_xfree(val->authorization_data.ciphertext.data); val->authorization_data.ciphertext.data = 0; } if (val->unenc_authdata) { krb5_free_authdata(context, val->unenc_authdata); val->unenc_authdata = 0; } if (val->second_ticket) { krb5_free_tickets(context, val->second_ticket); val->second_ticket = 0; } krb5_xfree(val); } #endif /* !_KERNEL */ /* * Delete a key's derived key list */ static void cleanup_dk_list(krb5_context context, krb5_keyblock *key) { krb5_dk_node *dn = key->dk_list; krb5_dk_node *nxt; while (dn != NULL) { nxt = dn->next; if (dn->derived_key != NULL) { /* * Some recursion here but its OK, * it stops when a NULL dk_list * is encountered. */ krb5_free_keyblock(context, dn->derived_key); dn->derived_key = NULL; } FREE(dn, sizeof(krb5_dk_node)); dn = nxt; } key->dk_list = NULL; } /* ARGSUSED */ void KRB5_CALLCONV krb5_free_keyblock_contents(krb5_context context, register krb5_keyblock *key) { if (key->contents) { (void) memset(key->contents, 0, key->length); krb5_xfree_wrap(key->contents, key->length); key->length = 0; key->contents = 0; } #ifdef _KERNEL if (key->key_tmpl != NULL) (void) crypto_destroy_ctx_template(key->key_tmpl); #else if (key->hKey != CK_INVALID_HANDLE) { CK_RV rv; rv = C_DestroyObject(krb_ctx_hSession(context), key->hKey); if (rv != CKR_OK) { KRB5_LOG(KRB5_ERR, "krb5_free_keyblock_contents: " "C_DestroyObject = %0x", rv); } key->hKey = CK_INVALID_HANDLE; } #endif /* _KERNEL */ /* * If the original key data is freed, we should also free * any keys derived from that data. * This saves us from making additional calls to "cleanup_dk_list" * in all of the many function which have keyblock structures * declared on the stack that re-use the keyblock data contents * without freeing the entire keyblock record. */ cleanup_dk_list(context, key); } void KRB5_CALLCONV krb5_free_keyblock(krb5_context context, register krb5_keyblock *val) { if (!val) return; krb5_free_keyblock_contents(context, val); krb5_xfree_wrap(val, sizeof(krb5_keyblock)); } #ifndef _KERNEL void KRB5_CALLCONV krb5_free_last_req(krb5_context context, krb5_last_req_entry **val) { register krb5_last_req_entry **temp; for (temp = val; *temp; temp++) krb5_xfree(*temp); krb5_xfree(val); } void KRB5_CALLCONV krb5_free_pa_data(krb5_context context, krb5_pa_data **val) { register krb5_pa_data **temp; for (temp = val; *temp; temp++) { if ((*temp)->contents) krb5_xfree((*temp)->contents); krb5_xfree(*temp); } krb5_xfree(val); } #endif /* !_KERNEL */ /* ARGSUSED */ void KRB5_CALLCONV krb5_free_principal(krb5_context context, krb5_principal val) { register krb5_int32 i; if (!val) return; if (val->data) { i = krb5_princ_size(context, val); while(--i >= 0) FREE(krb5_princ_component(context, val, i)->data, krb5_princ_component(context, val, i)->length+1); krb5_xfree_wrap(val->data, sizeof(krb5_data) * krb5_princ_size(context, val)); } if (val->realm.data) krb5_xfree_wrap(val->realm.data, val->realm.length+1); krb5_xfree_wrap(val, sizeof (krb5_principal_data)); } #ifndef _KERNEL void KRB5_CALLCONV krb5_free_priv(krb5_context context, register krb5_priv *val) { if (val->enc_part.ciphertext.data) { krb5_xfree(val->enc_part.ciphertext.data); val->enc_part.ciphertext.data = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_priv_enc_part(krb5_context context, register krb5_priv_enc_part *val) { if (val->user_data.data) { krb5_xfree(val->user_data.data); val->user_data.data = 0; } if (val->r_address) { krb5_free_address(context, val->r_address); val->r_address = 0; } if (val->s_address) { krb5_free_address(context, val->s_address); val->s_address = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_pwd_data(krb5_context context, krb5_pwd_data *val) { if (val->element) krb5_free_pwd_sequences(context, val->element); krb5_xfree(val); } void KRB5_CALLCONV krb5_free_pwd_sequences(krb5_context context, passwd_phrase_element **val) { register passwd_phrase_element **temp; for (temp = val; *temp; temp++) { if ((*temp)->passwd) { krb5_free_data(context, (*temp)->passwd); (*temp)->passwd = 0; } if ((*temp)->phrase) { krb5_free_data(context, (*temp)->phrase); (*temp)->phrase = 0; } krb5_xfree(*temp); } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_safe(krb5_context context, register krb5_safe *val) { if (val->user_data.data) { krb5_xfree(val->user_data.data); val->user_data.data = 0; } if (val->r_address) { krb5_free_address(context, val->r_address); val->r_address = 0; } if (val->s_address) { krb5_free_address(context, val->s_address); val->s_address = 0; } if (val->checksum) { krb5_free_checksum(context, val->checksum); val->checksum = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_ticket(krb5_context context, krb5_ticket *val) { if (val->server) krb5_free_principal(context, val->server); if (val->enc_part.ciphertext.data) { krb5_xfree(val->enc_part.ciphertext.data); val->enc_part.ciphertext.data = 0; } if (val->enc_part2) krb5_free_enc_tkt_part(context, val->enc_part2); krb5_xfree(val); } void KRB5_CALLCONV krb5_free_tickets(krb5_context context, krb5_ticket **val) { register krb5_ticket **temp; for (temp = val; *temp; temp++) krb5_free_ticket(context, *temp); krb5_xfree(val); } void KRB5_CALLCONV krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts) { register krb5_creds **tgtpp; for (tgtpp = tgts; *tgtpp; tgtpp++) krb5_free_creds(context, *tgtpp); krb5_xfree(tgts); } void KRB5_CALLCONV krb5_free_tkt_authent(krb5_context context, krb5_tkt_authent *val) { if (val->ticket) { krb5_free_ticket(context, val->ticket); val->ticket = 0; } if (val->authenticator) { krb5_free_authenticator(context, val->authenticator); val->authenticator = 0; } krb5_xfree(val); } void KRB5_CALLCONV krb5_free_unparsed_name(krb5_context context, char *val) { if (val) { krb5_xfree(val); } } void KRB5_CALLCONV krb5_free_sam_challenge(krb5_context ctx, krb5_sam_challenge *sc) { if (!sc) return; krb5_free_sam_challenge_contents(ctx, sc); krb5_xfree(sc); } void KRB5_CALLCONV krb5_free_sam_challenge_2(krb5_context ctx, krb5_sam_challenge_2 *sc2) { if (!sc2) return; krb5_free_sam_challenge_2_contents(ctx, sc2); krb5_xfree(sc2); } void KRB5_CALLCONV krb5_free_sam_challenge_contents(krb5_context ctx, krb5_sam_challenge *sc) { if (!sc) return; if (sc->sam_type_name.data) krb5_free_data_contents(ctx, &sc->sam_type_name); if (sc->sam_track_id.data) krb5_free_data_contents(ctx, &sc->sam_track_id); if (sc->sam_challenge_label.data) krb5_free_data_contents(ctx, &sc->sam_challenge_label); if (sc->sam_challenge.data) krb5_free_data_contents(ctx, &sc->sam_challenge); if (sc->sam_response_prompt.data) krb5_free_data_contents(ctx, &sc->sam_response_prompt); if (sc->sam_pk_for_sad.data) krb5_free_data_contents(ctx, &sc->sam_pk_for_sad); if (sc->sam_cksum.contents) { krb5_xfree(sc->sam_cksum.contents); sc->sam_cksum.contents = 0; } } void KRB5_CALLCONV krb5_free_sam_challenge_2_contents(krb5_context ctx, krb5_sam_challenge_2 *sc2) { krb5_checksum **cksump; if (!sc2) return; if (sc2->sam_challenge_2_body.data) krb5_free_data_contents(ctx, &sc2->sam_challenge_2_body); if (sc2->sam_cksum) { cksump = sc2->sam_cksum; while (*cksump) { krb5_free_checksum(ctx, *cksump); cksump++; } krb5_xfree(sc2->sam_cksum); sc2->sam_cksum = 0; } } void KRB5_CALLCONV krb5_free_sam_challenge_2_body(krb5_context ctx, krb5_sam_challenge_2_body *sc2) { if (!sc2) return; krb5_free_sam_challenge_2_body_contents(ctx, sc2); krb5_xfree(sc2); } void KRB5_CALLCONV krb5_free_sam_challenge_2_body_contents(krb5_context ctx, krb5_sam_challenge_2_body *sc2) { if (!sc2) return; if (sc2->sam_type_name.data) krb5_free_data_contents(ctx, &sc2->sam_type_name); if (sc2->sam_track_id.data) krb5_free_data_contents(ctx, &sc2->sam_track_id); if (sc2->sam_challenge_label.data) krb5_free_data_contents(ctx, &sc2->sam_challenge_label); if (sc2->sam_challenge.data) krb5_free_data_contents(ctx, &sc2->sam_challenge); if (sc2->sam_response_prompt.data) krb5_free_data_contents(ctx, &sc2->sam_response_prompt); if (sc2->sam_pk_for_sad.data) krb5_free_data_contents(ctx, &sc2->sam_pk_for_sad); } void KRB5_CALLCONV krb5_free_sam_response(krb5_context ctx, krb5_sam_response *sr) { if (!sr) return; krb5_free_sam_response_contents(ctx, sr); krb5_xfree(sr); } void KRB5_CALLCONV krb5_free_sam_response_2(krb5_context ctx, krb5_sam_response_2 *sr2) { if (!sr2) return; krb5_free_sam_response_2_contents(ctx, sr2); krb5_xfree(sr2); } void KRB5_CALLCONV krb5_free_sam_response_contents(krb5_context ctx, krb5_sam_response *sr) { if (!sr) return; if (sr->sam_track_id.data) krb5_free_data_contents(ctx, &sr->sam_track_id); if (sr->sam_enc_key.ciphertext.data) krb5_free_data_contents(ctx, &sr->sam_enc_key.ciphertext); if (sr->sam_enc_nonce_or_ts.ciphertext.data) krb5_free_data_contents(ctx, &sr->sam_enc_nonce_or_ts.ciphertext); } void KRB5_CALLCONV krb5_free_sam_response_2_contents(krb5_context ctx, krb5_sam_response_2 *sr2) { if (!sr2) return; if (sr2->sam_track_id.data) krb5_free_data_contents(ctx, &sr2->sam_track_id); if (sr2->sam_enc_nonce_or_sad.ciphertext.data) krb5_free_data_contents(ctx, &sr2->sam_enc_nonce_or_sad.ciphertext); } void KRB5_CALLCONV krb5_free_predicted_sam_response(krb5_context ctx, krb5_predicted_sam_response *psr) { if (!psr) return; krb5_free_predicted_sam_response_contents(ctx, psr); krb5_xfree(psr); } void KRB5_CALLCONV krb5_free_predicted_sam_response_contents(krb5_context ctx, krb5_predicted_sam_response *psr) { if (!psr) return; if (psr->sam_key.contents) krb5_free_keyblock_contents(ctx, &psr->sam_key); if (psr->client) { krb5_free_principal(ctx, psr->client); psr->client = 0; } if (psr->msd.data) krb5_free_data_contents(ctx, &psr->msd); } void KRB5_CALLCONV krb5_free_enc_sam_response_enc(krb5_context ctx, krb5_enc_sam_response_enc *esre) { if (!esre) return; krb5_free_enc_sam_response_enc_contents(ctx, esre); krb5_xfree(esre); } void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2(krb5_context ctx, krb5_enc_sam_response_enc_2 *esre2) { if (!esre2) return; krb5_free_enc_sam_response_enc_2_contents(ctx, esre2); krb5_xfree(esre2); } void KRB5_CALLCONV krb5_free_enc_sam_response_enc_contents(krb5_context ctx, krb5_enc_sam_response_enc *esre) { if (!esre) return; if (esre->sam_sad.data) krb5_free_data_contents(ctx, &esre->sam_sad); } void KRB5_CALLCONV krb5_free_enc_sam_response_enc_2_contents(krb5_context ctx, krb5_enc_sam_response_enc_2 *esre2) { if (!esre2) return; if (esre2->sam_sad.data) krb5_free_data_contents(ctx, &esre2->sam_sad); } void KRB5_CALLCONV krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts *pa_enc_ts) { if (!pa_enc_ts) return; krb5_xfree(pa_enc_ts); } #endif /* !_KERNEL */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/parse.c * * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * krb5_parse_name() routine. * * Rewritten by Theodore Ts'o to properly handle arbitrary quoted * characters in the principal name. */ #include "k5-int.h" /* * converts a single-string representation of the name to the * multi-part principal format used in the protocols. * * principal will point to allocated storage which should be freed by * the caller (using krb5_free_principal) after use. * * Conventions: / is used to separate components. If @ is present in the * string, then the rest of the string after it represents the realm name. * Otherwise the local realm name is used. * * error return: * KRB5_PARSE_MALFORMED badly formatted string * * also returns system errors: * ENOMEM malloc failed/out of memory * * get_default_realm() is called; it may return other errors. */ #define REALM_SEP '@' #define COMPONENT_SEP '/' #define QUOTECHAR '\\' #define FCOMPNUM 10 /* * May the fleas of a thousand camels infest the ISO, they who think * that arbitrarily large multi-component names are a Good Thing..... */ static krb5_error_code /*LINTED*/ k5_parse_name(krb5_context context, const char *name, int flags, krb5_principal *nprincipal) { register const char *cp; register char *q; register int i,c,size; int components = 0; const char *parsed_realm = NULL; int fcompsize[FCOMPNUM]; unsigned int realmsize = 0; #ifndef _KERNEL char *default_realm = NULL; int default_realm_size = 0; krb5_error_code retval; #endif char *tmpdata; krb5_principal principal; unsigned int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); int first_at; *nprincipal = NULL; /* * Pass 1. Find out how many components there are to the name, * and get string sizes for the first FCOMPNUM components. For * enterprise principal names (UPNs), there is only a single * component. */ size = 0; /*LINTED*/ for (i=0,cp = name, first_at = 1; (c = *cp); cp++) { if (c == QUOTECHAR) { cp++; /*LINTED*/ if (!(c = *cp)) /* * QUOTECHAR can't be at the last * character of the name! */ return(KRB5_PARSE_MALFORMED); size++; continue; } else if (c == COMPONENT_SEP && !enterprise) { if (parsed_realm) /* * Shouldn't see a component separator * after we've parsed out the realm name! */ return(KRB5_PARSE_MALFORMED); if (i < FCOMPNUM) { fcompsize[i] = size; } size = 0; i++; } else if (c == REALM_SEP && (!enterprise || !first_at)) { if (parsed_realm) /* * Multiple realm separaters * not allowed; zero-length realms are. */ return(KRB5_PARSE_MALFORMED); parsed_realm = cp + 1; if (i < FCOMPNUM) { fcompsize[i] = size; } size = 0; } else { if (c == REALM_SEP && enterprise && first_at) first_at = 0; size++; } } if (parsed_realm != NULL) realmsize = size; else if (i < FCOMPNUM) fcompsize[i] = size; components = i + 1; /* * Now, we allocate the principal structure and all of its * component pieces */ principal = (krb5_principal)MALLOC(sizeof(krb5_principal_data)); if (principal == NULL) { return(ENOMEM); } principal->data = (krb5_data *)MALLOC(sizeof(krb5_data) * components); if (principal->data == NULL) { krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); return ENOMEM; } principal->length = components; /* * If a realm was not found, then use the default realm, unless * KRB5_PRINCIPAL_PARSE_NO_REALM was specified in which case the * realm will be empty. */ #ifndef _KERNEL if (!parsed_realm) { if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) { krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "Principal %s is missing required realm", name); krb5_xfree_wrap(principal->data, principal->length); krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); return KRB5_PARSE_MALFORMED; } if (!default_realm && (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) == 0) { retval = krb5_get_default_realm(context, &default_realm); if (retval) { krb5_xfree_wrap(principal->data, principal->length); krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); return(retval); } default_realm_size = strlen(default_realm); } realmsize = default_realm_size; } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "Principal %s has realm present", name); krb5_xfree_wrap(principal->data, principal->length); krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); return KRB5_PARSE_MALFORMED; } #endif /* * Pass 2. Happens only if there were more than FCOMPNUM * component; if this happens, someone should be shot * immediately. Nevertheless, we will attempt to handle said * case..... */ if (components >= FCOMPNUM) { size = 0; parsed_realm = NULL; /*LINTED*/ for (i=0,cp = name; (c = *cp); cp++) { if (c == QUOTECHAR) { cp++; size++; } else if (c == COMPONENT_SEP) { if (krb5_princ_size(context, principal) > i) krb5_princ_component(context, principal, i)->length = size; size = 0; i++; } else if (c == REALM_SEP) { if (krb5_princ_size(context, principal) > i) krb5_princ_component(context, principal, i)->length = size; size = 0; parsed_realm = cp+1; } else size++; } if (parsed_realm) krb5_princ_realm(context, principal)->length = size; else if (krb5_princ_size(context, principal) > i) krb5_princ_component(context, principal, i)->length = size; if (i + 1 != components) { #ifndef _KERNEL #if !defined(_WIN32) fprintf(stderr, "Programming error in krb5_parse_name!"); #endif ASSERT(i + 1 == components); abort(); #else ASSERT(i + 1 == components); #endif /* !_KERNEL */ } } else { /* * If there were fewer than FCOMPSIZE components (the * usual case), then just copy the sizes to the * principal structure */ for (i=0; i < components; i++) krb5_princ_component(context, principal, i)->length = fcompsize[i]; } /* * Now, we need to allocate the space for the strings themselves..... */ tmpdata = MALLOC(realmsize + 1); if (tmpdata == 0) { krb5_xfree_wrap(principal->data, principal->length); krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); #ifndef _KERNEL krb5_xfree_wrap(default_realm, strlen(default_realm)); #endif return ENOMEM; } krb5_princ_set_realm_length(context, principal, realmsize); krb5_princ_set_realm_data(context, principal, tmpdata); for (i=0; i < components; i++) { char *tmpdata2 = MALLOC(krb5_princ_component(context, principal, i)->length + 1); if (tmpdata2 == NULL) { for (i--; i >= 0; i--) krb5_xfree_wrap(krb5_princ_component(context, principal, i)->data, krb5_princ_component(context, principal, i)->length + 1); krb5_xfree_wrap(krb5_princ_realm(context, principal)->data, krb5_princ_realm(context, principal)->length + 1); krb5_xfree_wrap(principal->data, principal->length); krb5_xfree_wrap(principal, sizeof(krb5_principal_data)); #ifndef _KERNEL krb5_xfree_wrap(default_realm, strlen(default_realm)); #endif return(ENOMEM); } krb5_princ_component(context, principal, i)->data = tmpdata2; krb5_princ_component(context, principal, i)->magic = KV5M_DATA; } /* * Pass 3. Now we go through the string a *third* time, this * time filling in the krb5_principal structure which we just * allocated. */ q = krb5_princ_component(context, principal, 0)->data; /*LINTED*/ for (i=0,cp = name, first_at = 1; (c = *cp); cp++) { if (c == QUOTECHAR) { cp++; switch (c = *cp) { case 'n': *q++ = '\n'; break; case 't': *q++ = '\t'; break; case 'b': *q++ = '\b'; break; case '0': *q++ = '\0'; break; default: *q++ = c; break; } } else if (c == COMPONENT_SEP && !enterprise) { i++; *q++ = '\0'; q = krb5_princ_component(context, principal, i)->data; } else if (c == REALM_SEP && (!enterprise || !first_at)) { i++; *q++ = '\0'; q = krb5_princ_realm(context, principal)->data; } else { if (c == REALM_SEP && enterprise && first_at) first_at = 0; *q++ = c; } } *q++ = '\0'; /*LINTED*/ if (!parsed_realm) { #ifndef _KERNEL if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) (krb5_princ_realm(context, principal)->data)[0] = '\0'; else strlcpy(krb5_princ_realm(context, principal)->data, default_realm, realmsize+1); #endif } /* * Alright, we're done. Now stuff a pointer to this monstrosity * into the return variable, and let's get out of here. */ if (enterprise) krb5_princ_type(context, principal) = KRB5_NT_ENTERPRISE_PRINCIPAL; else krb5_princ_type(context, principal) = KRB5_NT_PRINCIPAL; principal->magic = KV5M_PRINCIPAL; principal->realm.magic = KV5M_DATA; *nprincipal = principal; #ifndef _KERNEL if (default_realm != NULL) krb5_xfree_wrap(default_realm, strlen(default_realm)); #endif return(0); } krb5_error_code KRB5_CALLCONV krb5_parse_name(krb5_context context, const char *name, krb5_principal *nprincipal) { return k5_parse_name(context, name, 0, nprincipal); } krb5_error_code KRB5_CALLCONV krb5_parse_name_flags(krb5_context context, const char *name, int flags, krb5_principal *nprincipal) { return k5_parse_name(context, name, flags, nprincipal); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/ser_actx.c * * Copyright 1995 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. * */ /* * ser_actx.c - Serialize krb5_auth_context structure. */ #include "k5-int.h" #include "int-proto.h" #include "auth_con.h" #define TOKEN_RADDR 950916 #define TOKEN_RPORT 950917 #define TOKEN_LADDR 950918 #define TOKEN_LPORT 950919 #define TOKEN_KEYBLOCK 950920 #define TOKEN_LSKBLOCK 950921 #define TOKEN_RSKBLOCK 950922 /* * Routines to deal with externalizing the krb5_auth_context: * krb5_auth_context_size(); * krb5_auth_context_externalize(); * krb5_auth_context_internalize(); */ static krb5_error_code krb5_auth_context_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_auth_context_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_auth_context_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* * Other metadata serialization initializers. */ /* Local data */ static const krb5_ser_entry krb5_auth_context_ser_entry = { KV5M_AUTH_CONTEXT, /* Type */ krb5_auth_context_size, /* Sizer routine */ krb5_auth_context_externalize, /* Externalize routine */ krb5_auth_context_internalize /* Internalize routine */ }; /* * krb5_auth_context_size() - Determine the size required to externalize * the krb5_auth_context. */ static krb5_error_code krb5_auth_context_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_auth_context auth_context; size_t required; /* * krb5_auth_context requires at minimum: * krb5_int32 for KV5M_AUTH_CONTEXT * krb5_int32 for auth_context_flags * krb5_int32 for remote_seq_number * krb5_int32 for local_seq_number * krb5_int32 for req_cksumtype * krb5_int32 for safe_cksumtype * krb5_int32 for size of i_vector * krb5_int32 for KV5M_AUTH_CONTEXT */ kret = EINVAL; /* Solaris Kerberos */ auth_context = (krb5_auth_context) arg; if (auth_context) { kret = 0; /* Calculate size required by i_vector - ptooey */ if (auth_context->i_vector && auth_context->keyblock) { kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype, &required); } else { required = 0; } required += sizeof(krb5_int32)*8; /* Calculate size required by remote_addr, if appropriate */ if (!kret && auth_context->remote_addr) { kret = krb5_size_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->remote_addr, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by remote_port, if appropriate */ if (!kret && auth_context->remote_port) { kret = krb5_size_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->remote_port, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by local_addr, if appropriate */ if (!kret && auth_context->local_addr) { kret = krb5_size_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->local_addr, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by local_port, if appropriate */ if (!kret && auth_context->local_port) { kret = krb5_size_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->local_port, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by keyblock, if appropriate */ if (!kret && auth_context->keyblock) { kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->keyblock, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by send_subkey, if appropriate */ if (!kret && auth_context->send_subkey) { kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->send_subkey, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by recv_subkey, if appropriate */ if (!kret && auth_context->recv_subkey) { kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->recv_subkey, &required); if (!kret) required += sizeof(krb5_int32); } /* Calculate size required by authentp, if appropriate */ if (!kret && auth_context->authentp) kret = krb5_size_opaque(kcontext, KV5M_AUTHENTICATOR, (krb5_pointer) auth_context->authentp, &required); } if (!kret) *sizep += required; return(kret); } /* * krb5_auth_context_externalize() - Externalize the krb5_auth_context. */ static krb5_error_code krb5_auth_context_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_auth_context auth_context; size_t required; krb5_octet *bp; size_t remain; size_t obuf; krb5_int32 obuf32; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ auth_context = (krb5_auth_context) arg; if (auth_context) { kret = ENOMEM; if (!krb5_auth_context_size(kcontext, arg, &required) && (required <= remain)) { /* Write fixed portion */ (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); (void) krb5_ser_pack_int32(auth_context->auth_context_flags, &bp, &remain); (void) krb5_ser_pack_int32(auth_context->remote_seq_number, &bp, &remain); (void) krb5_ser_pack_int32(auth_context->local_seq_number, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) auth_context->req_cksumtype, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype, &bp, &remain); kret = 0; /* Now figure out the number of bytes for i_vector and write it */ if (auth_context->i_vector) { kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype, &obuf); } else { obuf = 0; } /* Convert to signed 32 bit integer */ obuf32 = obuf; if (kret == 0 && obuf != obuf32) kret = EINVAL; if (!kret) (void) krb5_ser_pack_int32(obuf32, &bp, &remain); /* Now copy i_vector */ if (!kret && auth_context->i_vector) (void) krb5_ser_pack_bytes(auth_context->i_vector, obuf, &bp, &remain); /* Now handle remote_addr, if appropriate */ if (!kret && auth_context->remote_addr) { (void) krb5_ser_pack_int32(TOKEN_RADDR, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->remote_addr, &bp, &remain); } /* Now handle remote_port, if appropriate */ if (!kret && auth_context->remote_port) { (void) krb5_ser_pack_int32(TOKEN_RPORT, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->remote_addr, &bp, &remain); } /* Now handle local_addr, if appropriate */ if (!kret && auth_context->local_addr) { (void) krb5_ser_pack_int32(TOKEN_LADDR, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->local_addr, &bp, &remain); } /* Now handle local_port, if appropriate */ if (!kret && auth_context->local_port) { (void) krb5_ser_pack_int32(TOKEN_LPORT, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->local_addr, &bp, &remain); } /* Now handle keyblock, if appropriate */ if (!kret && auth_context->keyblock) { (void) krb5_ser_pack_int32(TOKEN_KEYBLOCK, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->keyblock, &bp, &remain); } /* Now handle subkey, if appropriate */ if (!kret && auth_context->send_subkey) { (void) krb5_ser_pack_int32(TOKEN_LSKBLOCK, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->send_subkey, &bp, &remain); } /* Now handle subkey, if appropriate */ if (!kret && auth_context->recv_subkey) { (void) krb5_ser_pack_int32(TOKEN_RSKBLOCK, &bp, &remain); kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) auth_context->recv_subkey, &bp, &remain); } /* Now handle authentp, if appropriate */ if (!kret && auth_context->authentp) kret = krb5_externalize_opaque(kcontext, KV5M_AUTHENTICATOR, (krb5_pointer) auth_context->authentp, &bp, &remain); /* * If we were successful, write trailer then update the pointer and * remaining length; */ if (!kret) { /* Write our trailer */ (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); *buffer = bp; *lenremain = remain; } } } return(kret); } /* * krb5_auth_context_internalize() - Internalize the krb5_auth_context. */ static krb5_error_code krb5_auth_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_auth_context auth_context; krb5_int32 ibuf; krb5_octet *bp; size_t remain; krb5_int32 ivlen; krb5_int32 tag; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_AUTH_CONTEXT) { kret = ENOMEM; /* Get memory for the auth_context */ if ((remain >= (5*sizeof(krb5_int32))) && (auth_context = (krb5_auth_context) MALLOC(sizeof(struct _krb5_auth_context)))) { (void) memset(auth_context, 0, sizeof(struct _krb5_auth_context)); /* Get auth_context_flags */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->auth_context_flags = ibuf; /* Get remote_seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->remote_seq_number = ibuf; /* Get local_seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->local_seq_number = ibuf; /* Get req_cksumtype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->req_cksumtype = (krb5_cksumtype) ibuf; /* Get safe_cksumtype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); auth_context->safe_cksumtype = (krb5_cksumtype) ibuf; /* Get length of i_vector */ (void) krb5_ser_unpack_int32(&ivlen, &bp, &remain); if (ivlen) { if ((auth_context->i_vector = (krb5_pointer) MALLOC((size_t)ivlen))) kret = krb5_ser_unpack_bytes(auth_context->i_vector, (size_t) ivlen, &bp, &remain); else kret = ENOMEM; } else kret = 0; /* Peek at next token */ tag = 0; if (!kret) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); /* This is the remote_addr */ if (!kret && (tag == TOKEN_RADDR)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> remote_addr, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the remote_port */ if (!kret && (tag == TOKEN_RPORT)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> remote_port, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the local_addr */ if (!kret && (tag == TOKEN_LADDR)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> local_addr, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the local_port */ if (!kret && (tag == TOKEN_LPORT)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer *) &auth_context-> local_port, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the keyblock */ if (!kret && (tag == TOKEN_KEYBLOCK)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context->keyblock, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the send_subkey */ if (!kret && (tag == TOKEN_LSKBLOCK)) { if (!(kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context-> send_subkey, &bp, &remain))) kret = krb5_ser_unpack_int32(&tag, &bp, &remain); } /* This is the recv_subkey */ if (!kret) { if (tag == TOKEN_RSKBLOCK) { kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &auth_context-> recv_subkey, &bp, &remain); } else { /* * We read the next tag, but it's not of any use here, so * we effectively 'unget' it here. */ bp -= sizeof(krb5_int32); remain += sizeof(krb5_int32); } } /* Now find the authentp */ if (!kret) { if ((kret = krb5_internalize_opaque(kcontext, KV5M_AUTHENTICATOR, (krb5_pointer *) &auth_context->authentp, &bp, &remain))) { if (kret == EINVAL) kret = 0; } } /* Finally, find the trailer */ if (!kret) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf != KV5M_AUTH_CONTEXT)) kret = EINVAL; } if (!kret) { *buffer = bp; *lenremain = remain; auth_context->magic = KV5M_AUTH_CONTEXT; *argp = (krb5_pointer) auth_context; } /* We don't import the auth_context into the kernel */ #ifndef _KERNEL else krb5_auth_con_free(kcontext, auth_context); #endif } } return(kret); } /* * Register the auth_context serializer. */ krb5_error_code KRB5_CALLCONV krb5_ser_auth_context_init(krb5_context kcontext) { krb5_error_code kret; kret = krb5_register_serializer(kcontext, &krb5_auth_context_ser_entry); if (!kret) kret = krb5_ser_authdata_init(kcontext); if (!kret) kret = krb5_ser_address_init(kcontext); if (!kret) kret = krb5_ser_authenticator_init(kcontext); if (!kret) kret = krb5_ser_checksum_init(kcontext); if (!kret) kret = krb5_ser_keyblock_init(kcontext); if (!kret) kret = krb5_ser_principal_init(kcontext); return(kret); } /* * lib/krb5/krb/ser_adata.c * * Copyright 1995 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. * */ /* * ser_adata.c - Serialize a krb5_authdata structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_authdata: * krb5_authdata_size(); * krb5_authdata_externalize(); * krb5_authdata_internalize(); */ static krb5_error_code krb5_authdata_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_authdata_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_authdata_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_authdata_ser_entry = { KV5M_AUTHDATA, /* Type */ krb5_authdata_size, /* Sizer routine */ krb5_authdata_externalize, /* Externalize routine */ krb5_authdata_internalize /* Internalize routine */ }; /* * krb5_authdata_esize() - Determine the size required to externalize * the krb5_authdata. */ /*ARGSUSED*/ static krb5_error_code krb5_authdata_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_authdata *authdata; /* * krb5_authdata requires: * krb5_int32 for KV5M_AUTHDATA * krb5_int32 for ad_type * krb5_int32 for length * authdata->length for contents * krb5_int32 for KV5M_AUTHDATA */ kret = EINVAL; /* Solaris Kerberos */ authdata = (krb5_authdata *) arg; if (authdata) { *sizep += (sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + (size_t) authdata->length); kret = 0; } return(kret); } /* * krb5_authdata_externalize() - Externalize the krb5_authdata. */ static krb5_error_code krb5_authdata_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_authdata *authdata; size_t required; krb5_octet *bp; size_t remain; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ authdata = (krb5_authdata *) arg; if (authdata) { kret = ENOMEM; if (!krb5_authdata_size(kcontext, arg, &required) && (required <= remain)) { /* Our identifier */ (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain); /* Our ad_type */ (void) krb5_ser_pack_int32((krb5_int32) authdata->ad_type, &bp, &remain); /* Our length */ (void) krb5_ser_pack_int32((krb5_int32) authdata->length, &bp, &remain); /* Our contents */ (void) krb5_ser_pack_bytes(authdata->contents, (size_t) authdata->length, &bp, &remain); /* Finally, our trailer */ (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain); kret = 0; *buffer = bp; *lenremain = remain; } } return(kret); } /* * krb5_authdata_internalize() - Internalize the krb5_authdata. */ /*ARGSUSED*/ static krb5_error_code krb5_authdata_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_authdata *authdata; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_AUTHDATA) { kret = ENOMEM; /* Get a authdata */ if ((remain >= (2*sizeof(krb5_int32))) && (authdata = (krb5_authdata *) MALLOC(sizeof(krb5_authdata)))) { (void) memset(authdata, 0, sizeof(krb5_authdata)); /* Get the ad_type */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authdata->ad_type = (krb5_authdatatype) ibuf; /* Get the length */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authdata->length = (int) ibuf; /* Get the string */ /* Solaris Kerberos */ authdata->contents = (krb5_octet *) MALLOC((size_t) (ibuf)); if ((authdata->contents) && !(kret = krb5_ser_unpack_bytes(authdata->contents, (size_t) ibuf, &bp, &remain))) { if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) ibuf = 0; if (ibuf == KV5M_AUTHDATA) { authdata->magic = KV5M_AUTHDATA; *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) authdata; } else kret = EINVAL; } if (kret) { if (authdata->contents) FREE(authdata->contents, authdata->length); FREE(authdata, sizeof (krb5_authdata)); } } } return(kret); } /* * Register the authdata serializer. */ krb5_error_code krb5_ser_authdata_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_authdata_ser_entry)); } /* * lib/krb5/krb/ser_addr.c * * Copyright 1995 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. * */ /* * ser_addr.c - Serialize a krb5_address structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_address: * krb5_address_size(); * krb5_address_externalize(); * krb5_address_internalize(); */ static krb5_error_code krb5_address_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_address_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_address_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_address_ser_entry = { KV5M_ADDRESS, /* Type */ krb5_address_size, /* Sizer routine */ krb5_address_externalize, /* Externalize routine */ krb5_address_internalize /* Internalize routine */ }; /* * krb5_address_size() - Determine the size required to externalize * the krb5_address. */ /*ARGSUSED*/ static krb5_error_code krb5_address_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_address *address; /* * krb5_address requires: * krb5_int32 for KV5M_ADDRESS * krb5_int32 for addrtype * krb5_int32 for length * address->length for contents * krb5_int32 for KV5M_ADDRESS */ kret = EINVAL; /* Solaris Kerberos */ address = (krb5_address *) arg; if (address) { *sizep += (sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + (size_t) address->length); kret = 0; } return(kret); } /* * krb5_address_externalize() - Externalize the krb5_address. */ static krb5_error_code krb5_address_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_address *address; size_t required; krb5_octet *bp; size_t remain; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ address = (krb5_address *) arg; if (address) { kret = ENOMEM; if (!krb5_address_size(kcontext, arg, &required) && (required <= remain)) { /* Our identifier */ (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain); /* Our addrtype */ (void) krb5_ser_pack_int32((krb5_int32) address->addrtype, &bp, &remain); /* Our length */ (void) krb5_ser_pack_int32((krb5_int32) address->length, &bp, &remain); /* Our contents */ (void) krb5_ser_pack_bytes(address->contents, (size_t) address->length, &bp, &remain); /* Finally, our trailer */ (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain); kret = 0; *buffer = bp; *lenremain = remain; } } return(kret); } /* * krb5_address_internalize() - Internalize the krb5_address. */ /*ARGSUSED*/ static krb5_error_code krb5_address_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_address *address; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_ADDRESS) { kret = ENOMEM; /* Get a address */ if ((remain >= (2*sizeof(krb5_int32))) && (address = (krb5_address *) MALLOC(sizeof(krb5_address)))) { (void) memset(address, 0, sizeof(krb5_address)); address->magic = KV5M_ADDRESS; /* Get the addrtype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); address->addrtype = (krb5_addrtype) ibuf; /* Get the length */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); address->length = (int) ibuf; /* Get the string */ /* Solaris Kerberos */ address->contents = (krb5_octet *) MALLOC((size_t) (ibuf)); if ((address->contents) && !(kret = krb5_ser_unpack_bytes(address->contents, (size_t) ibuf, &bp, &remain))) { /* Get the trailer */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) ibuf = 0; if (!kret && (ibuf == KV5M_ADDRESS)) { address->magic = KV5M_ADDRESS; *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) address; } else kret = EINVAL; } if (kret) { if (address->contents) FREE(address->contents, address->length); FREE(address, sizeof (krb5_address)); } } } return(kret); } /* * Register the address serializer. */ krb5_error_code krb5_ser_address_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_address_ser_entry)); } /* * lib/krb5/krb/ser_auth.c * * Copyright 1995 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. * */ /* * ser_auth.c - Serialize krb5_authenticator structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_authenticator: * krb5_authenticator_size(); * krb5_authenticator_externalize(); * krb5_authenticator_internalize(); */ static krb5_error_code krb5_authenticator_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_authenticator_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_authenticator_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_authenticator_ser_entry = { KV5M_AUTHENTICATOR, /* Type */ krb5_authenticator_size, /* Sizer routine */ krb5_authenticator_externalize, /* Externalize routine */ krb5_authenticator_internalize /* Internalize routine */ }; /* * krb5_authenticator_size() - Determine the size required to externalize * the krb5_authenticator. */ static krb5_error_code krb5_authenticator_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_authenticator *authenticator; size_t required; /* * krb5_authenticator requires at minimum: * krb5_int32 for KV5M_AUTHENTICATOR * krb5_int32 for seconds * krb5_int32 for cusec * krb5_int32 for seq_number * krb5_int32 for number in authorization_data array. * krb5_int32 for KV5M_AUTHENTICATOR */ kret = EINVAL; /* Solaris Kerberos */ authenticator = (krb5_authenticator *) arg; if (authenticator) { required = sizeof(krb5_int32)*6; /* Calculate size required by client, if appropriate */ if (authenticator->client) kret = krb5_size_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) authenticator->client, &required); else kret = 0; /* Calculate size required by checksum, if appropriate */ if (!kret && authenticator->checksum) kret = krb5_size_opaque(kcontext, KV5M_CHECKSUM, (krb5_pointer) authenticator->checksum, &required); /* Calculate size required by subkey, if appropriate */ if (!kret && authenticator->subkey) kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) authenticator->subkey, &required); /* Calculate size required by authorization_data, if appropriate */ if (!kret && authenticator->authorization_data) { int i; for (i=0; !kret && authenticator->authorization_data[i]; i++) { kret = krb5_size_opaque(kcontext, KV5M_AUTHDATA, (krb5_pointer) authenticator-> authorization_data[i], &required); } } } if (!kret) *sizep += required; return(kret); } /* * krb5_authenticator_externalize() - Externalize the krb5_authenticator. */ static krb5_error_code krb5_authenticator_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_authenticator *authenticator; size_t required; krb5_octet *bp; size_t remain; int i; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ authenticator = (krb5_authenticator *) arg; if (authenticator) { kret = ENOMEM; if (!krb5_authenticator_size(kcontext, arg, &required) && (required <= remain)) { /* First write our magic number */ (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); /* Now ctime */ (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime, &bp, &remain); /* Now cusec */ (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec, &bp, &remain); /* Now seq_number */ (void) krb5_ser_pack_int32(authenticator->seq_number, &bp, &remain); /* Now handle client, if appropriate */ if (authenticator->client) kret = krb5_externalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) authenticator->client, &bp, &remain); else kret = 0; /* Now handle checksum, if appropriate */ if (!kret && authenticator->checksum) kret = krb5_externalize_opaque(kcontext, KV5M_CHECKSUM, (krb5_pointer) authenticator->checksum, &bp, &remain); /* Now handle subkey, if appropriate */ if (!kret && authenticator->subkey) kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) authenticator->subkey, &bp, &remain); /* Now handle authorization_data, if appropriate */ if (!kret) { if (authenticator->authorization_data) for (i=0; authenticator->authorization_data[i]; i++); else i = 0; (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain); /* Now pound out the authorization_data */ if (authenticator->authorization_data) { for (i=0; !kret && authenticator->authorization_data[i]; i++) kret = krb5_externalize_opaque(kcontext, KV5M_AUTHDATA, (krb5_pointer) authenticator-> authorization_data[i], &bp, &remain); } } /* * If we were successful, write trailer then update the pointer and * remaining length; */ if (!kret) { /* Write our trailer */ (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); *buffer = bp; *lenremain = remain; } } } return(kret); } /* * krb5_authenticator_internalize() - Internalize the krb5_authenticator. */ static krb5_error_code krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_authenticator *authenticator; krb5_int32 ibuf; krb5_octet *bp; size_t remain; int i; krb5_int32 nadata; size_t len; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_AUTHENTICATOR) { kret = ENOMEM; /* Get memory for the authenticator */ if ((remain >= (3*sizeof(krb5_int32))) && (authenticator = (krb5_authenticator *) MALLOC(sizeof(krb5_authenticator)))) { (void) memset(authenticator, 0, sizeof(krb5_authenticator)); /* Get ctime */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->ctime = (krb5_timestamp) ibuf; /* Get cusec */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->cusec = ibuf; /* Get seq_number */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); authenticator->seq_number = ibuf; kret = 0; /* Attempt to read in the client */ kret = krb5_internalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer *) &authenticator->client, &bp, &remain); if (kret == EINVAL) kret = 0; /* Attempt to read in the checksum */ if (!kret) { kret = krb5_internalize_opaque(kcontext, KV5M_CHECKSUM, (krb5_pointer *) &authenticator->checksum, &bp, &remain); if (kret == EINVAL) kret = 0; } /* Attempt to read in the subkey */ if (!kret) { kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &authenticator->subkey, &bp, &remain); if (kret == EINVAL) kret = 0; } /* Attempt to read in the authorization data count */ if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { nadata = ibuf; len = (size_t) (nadata + 1); /* Get memory for the authorization data pointers */ if ((authenticator->authorization_data = (krb5_authdata **) MALLOC(sizeof(krb5_authdata *) * len))) { (void) memset(authenticator->authorization_data, 0, sizeof(krb5_authdata *) * len); for (i=0; !kret && (i authorization_data[i], &bp, &remain); } /* Finally, find the trailer */ if (!kret) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf == KV5M_AUTHENTICATOR)) authenticator->magic = KV5M_AUTHENTICATOR; else kret = EINVAL; } } } if (!kret) { *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) authenticator; } else krb5_free_authenticator(kcontext, authenticator); } } return(kret); } /* * Register the authenticator serializer. */ krb5_error_code krb5_ser_authenticator_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry)); } /* * lib/krb5/krb/ser_cksum.c * * Copyright 1995 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. * */ /* * ser_cksum.c - Serialize a krb5_checksum structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_checksum: * krb5_checksum_esize(); * krb5_checksum_externalize(); * krb5_checksum_internalize(); */ static krb5_error_code krb5_checksum_esize (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_checksum_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_checksum_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_checksum_ser_entry = { KV5M_CHECKSUM, /* Type */ krb5_checksum_esize, /* Sizer routine */ krb5_checksum_externalize, /* Externalize routine */ krb5_checksum_internalize /* Internalize routine */ }; /* * krb5_checksum_esize() - Determine the size required to externalize * the krb5_checksum. */ /*ARGSUSED*/ static krb5_error_code krb5_checksum_esize(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_checksum *checksum; /* * krb5_checksum requires: * krb5_int32 for KV5M_CHECKSUM * krb5_int32 for checksum_type * krb5_int32 for length * krb5_int32 for KV5M_CHECKSUM * checksum->length for contents */ kret = EINVAL; /* Solaris Kerberos */ checksum = (krb5_checksum *) arg; if (checksum) { *sizep += (sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + (size_t) checksum->length); kret = 0; } return(kret); } /* * krb5_checksum_externalize() - Externalize the krb5_checksum. */ static krb5_error_code krb5_checksum_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_checksum *checksum; size_t required; krb5_octet *bp; size_t remain; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ checksum = (krb5_checksum *) arg; if (checksum) { kret = ENOMEM; if (!krb5_checksum_esize(kcontext, arg, &required) && (required <= remain)) { /* Our identifier */ (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain); /* Our checksum_type */ (void) krb5_ser_pack_int32((krb5_int32) checksum->checksum_type, &bp, &remain); /* Our length */ (void) krb5_ser_pack_int32((krb5_int32) checksum->length, &bp, &remain); /* Our contents */ (void) krb5_ser_pack_bytes(checksum->contents, (size_t) checksum->length, &bp, &remain); /* Finally, our trailer */ (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain); kret = 0; *buffer = bp; *lenremain = remain; } } return(kret); } /* * krb5_checksum_internalize() - Internalize the krb5_checksum. */ /*ARGSUSED*/ static krb5_error_code krb5_checksum_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_checksum *checksum; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_CHECKSUM) { kret = ENOMEM; /* Get a checksum */ if ((remain >= (2*sizeof(krb5_int32))) && (checksum = (krb5_checksum *) MALLOC(sizeof(krb5_checksum)))) { (void) memset(checksum, 0, sizeof(krb5_checksum)); /* Get the checksum_type */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); checksum->checksum_type = (krb5_cksumtype) ibuf; /* Get the length */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); checksum->length = (int) ibuf; /* Get the string */ /* Solaris Kerberos */ if (ibuf) checksum->contents = (krb5_octet *) MALLOC((size_t) (ibuf)); if (!ibuf || ((checksum->contents) && !(kret = krb5_ser_unpack_bytes(checksum->contents, (size_t) ibuf, &bp, &remain)))) { /* Get the trailer */ kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf == KV5M_CHECKSUM)) { checksum->magic = KV5M_CHECKSUM; *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) checksum; } else kret = EINVAL; } if (kret) { if (checksum->contents) FREE(checksum->contents, checksum->length); FREE(checksum, sizeof (krb5_checksum)); } } } return(kret); } /* * Register the checksum serializer. */ krb5_error_code krb5_ser_checksum_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_checksum_ser_entry)); } /* * lib/krb5/krb/ser_ctx.c * * Copyright 1995 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. * */ /* * ser_ctx.c - Routines to deal with serializing the krb5_context and * krb5_os_context structures. */ #include "k5-int.h" /* * Routines to deal with externalizing the krb5_context: * krb5_context_size(); * krb5_context_externalize(); * krb5_context_internalize(); * * Routines to deal with externalizing the krb5_os_context: * krb5_oscontext_size(); * krb5_oscontext_externalize(); * krb5_oscontext_internalize(); * * Routines to deal with externalizing the profile. * profile_ser_size(); * profile_ser_externalize(); * profile_ser_internalize(); * * Interface to initialize serializing of krb5_context and krb5_os_context: * krb5_ser_context_init(); */ static krb5_error_code krb5_context_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_context_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_context_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); static krb5_error_code krb5_oscontext_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_oscontext_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_oscontext_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); #ifndef _KERNEL krb5_error_code profile_ser_size (krb5_context, krb5_pointer, size_t *); krb5_error_code profile_ser_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); krb5_error_code profile_ser_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); #endif /* Local data */ static const krb5_ser_entry krb5_context_ser_entry = { KV5M_CONTEXT, /* Type */ krb5_context_size, /* Sizer routine */ krb5_context_externalize, /* Externalize routine */ krb5_context_internalize /* Internalize routine */ }; static const krb5_ser_entry krb5_oscontext_ser_entry = { KV5M_OS_CONTEXT, /* Type */ krb5_oscontext_size, /* Sizer routine */ krb5_oscontext_externalize, /* Externalize routine */ krb5_oscontext_internalize /* Internalize routine */ }; #ifndef _KERNEL static const krb5_ser_entry krb5_profile_ser_entry = { PROF_MAGIC_PROFILE, /* Type */ profile_ser_size, /* Sizer routine */ profile_ser_externalize, /* Externalize routine */ profile_ser_internalize /* Internalize routine */ }; #endif /* * krb5_context_size() - Determine the size required to externalize the * krb5_context. */ static krb5_error_code krb5_context_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; size_t required; krb5_context context; /* * The KRB5 context itself requires: * krb5_int32 for KV5M_CONTEXT * krb5_int32 for sizeof(default_realm) * strlen(default_realm) for default_realm. * krb5_int32 for n_in_tkt_ktypes*sizeof(krb5_int32) * nktypes*sizeof(krb5_int32) for in_tkt_ktypes. * krb5_int32 for n_tgs_ktypes*sizeof(krb5_int32) * nktypes*sizeof(krb5_int32) for tgs_ktypes. * krb5_int32 for clockskew * krb5_int32 for kdc_req_sumtype * krb5_int32 for ap_req_sumtype * krb5_int32 for safe_sumtype * krb5_int32 for kdc_default_options * krb5_int32 for library_options * krb5_int32 for profile_secure * krb5_int32 for fcc_default_format * krb5_int32 for scc_default_format * <> for os_context * <> for db_context * <> for profile * krb5_int32 for trailer. */ kret = EINVAL; if ((context = (krb5_context) arg)) { /* Calculate base length */ required = (14 * sizeof(krb5_int32) + (context->in_tkt_ktype_count * sizeof(krb5_int32)) + (context->tgs_ktype_count * sizeof(krb5_int32))); if (context->default_realm) required += strlen(context->default_realm); /* Calculate size required by os_context, if appropriate */ if (context->os_context) kret = krb5_size_opaque(kcontext, KV5M_OS_CONTEXT, (krb5_pointer) context->os_context, &required); /* Calculate size required by db_context, if appropriate */ if (!kret && context->db_context) kret = krb5_size_opaque(kcontext, KV5M_DB_CONTEXT, (krb5_pointer) context->db_context, &required); /* Finally, calculate size required by profile, if appropriate */ if (!kret && context->profile) kret = krb5_size_opaque(kcontext, PROF_MAGIC_PROFILE, (krb5_pointer) context->profile, &required); } if (!kret) *sizep += required; return(kret); } /* * krb5_context_externalize() - Externalize the krb5_context. */ static krb5_error_code krb5_context_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_context context; size_t required; krb5_octet *bp; size_t remain; int i; required = 0; bp = *buffer; remain = *lenremain; context = (krb5_context) arg; if (!context) return (EINVAL); KRB5_VERIFY_MAGIC(context, KV5M_CONTEXT); if ((kret = krb5_context_size(kcontext, arg, &required))) return (kret); if (required > remain) return (ENOMEM); /* First write our magic number */ kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain); if (kret) return (kret); /* Now sizeof default realm */ kret = krb5_ser_pack_int32((context->default_realm) ? (krb5_int32) strlen(context->default_realm) : 0, &bp, &remain); if (kret) return (kret); /* Now default_realm bytes */ if (context->default_realm) { kret = krb5_ser_pack_bytes((krb5_octet *) context->default_realm, strlen(context->default_realm), &bp, &remain); if (kret) return (kret); } /* Now number of initial ticket ktypes */ kret = krb5_ser_pack_int32((krb5_int32) context->in_tkt_ktype_count, &bp, &remain); if (kret) return (kret); /* Now serialize ktypes */ for (i=0; iin_tkt_ktype_count; i++) { kret = krb5_ser_pack_int32((krb5_int32) context->in_tkt_ktypes[i], &bp, &remain); if (kret) return (kret); } /* Now number of default ktypes */ kret = krb5_ser_pack_int32((krb5_int32) context->tgs_ktype_count, &bp, &remain); if (kret) return (kret); /* Now serialize ktypes */ for (i=0; itgs_ktype_count; i++) { kret = krb5_ser_pack_int32((krb5_int32) context->tgs_ktypes[i], &bp, &remain); if (kret) return (kret); } /* Now allowable clockskew */ kret = krb5_ser_pack_int32((krb5_int32) context->clockskew, &bp, &remain); if (kret) return (kret); /* Now kdc_req_sumtype */ kret = krb5_ser_pack_int32((krb5_int32) context->kdc_req_sumtype, &bp, &remain); if (kret) return (kret); /* Now default ap_req_sumtype */ kret = krb5_ser_pack_int32((krb5_int32) context->default_ap_req_sumtype, &bp, &remain); if (kret) return (kret); /* Now default safe_sumtype */ kret = krb5_ser_pack_int32((krb5_int32) context->default_safe_sumtype, &bp, &remain); if (kret) return (kret); /* Now kdc_default_options */ kret = krb5_ser_pack_int32((krb5_int32) context->kdc_default_options, &bp, &remain); if (kret) return (kret); /* Now library_options */ kret = krb5_ser_pack_int32((krb5_int32) context->library_options, &bp, &remain); if (kret) return (kret); /* Now profile_secure */ kret = krb5_ser_pack_int32((krb5_int32) context->profile_secure, &bp, &remain); if (kret) return (kret); /* Now fcc_default_format */ kret = krb5_ser_pack_int32((krb5_int32) context->fcc_default_format, &bp, &remain); if (kret) return (kret); /* Now scc_default_format */ kret = krb5_ser_pack_int32((krb5_int32) context->scc_default_format, &bp, &remain); if (kret) return (kret); /* Now handle os_context, if appropriate */ if (context->os_context) { kret = krb5_externalize_opaque(kcontext, KV5M_OS_CONTEXT, (krb5_pointer) context->os_context, &bp, &remain); if (kret) return (kret); } /* Now handle database context, if appropriate */ if (context->db_context) { kret = krb5_externalize_opaque(kcontext, KV5M_DB_CONTEXT, (krb5_pointer) context->db_context, &bp, &remain); if (kret) return (kret); } /* Finally, handle profile, if appropriate */ if (context->profile) { kret = krb5_externalize_opaque(kcontext, PROF_MAGIC_PROFILE, (krb5_pointer) context->profile, &bp, &remain); if (kret) return (kret); } /* * If we were successful, write trailer then update the pointer and * remaining length; */ kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain); if (kret) return (kret); *buffer = bp; *lenremain = remain; return (0); } /* * krb5_context_internalize() - Internalize the krb5_context. */ static krb5_error_code krb5_context_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_context context; krb5_int32 ibuf; krb5_octet *bp; size_t remain; int i; bp = *buffer; remain = *lenremain; /* Read our magic number */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) return (EINVAL); if (ibuf != KV5M_CONTEXT) return (EINVAL); /* Get memory for the context */ context = (krb5_context) MALLOC(sizeof(struct _krb5_context)); if (!context) return (ENOMEM); (void) memset(context, 0, sizeof(struct _krb5_context)); /* Get the size of the default realm */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; if (ibuf) { context->default_realm = (char *) MALLOC((size_t) ibuf+1); if (!context->default_realm) { kret = ENOMEM; goto cleanup; } kret = krb5_ser_unpack_bytes((krb5_octet *) context->default_realm, (size_t) ibuf, &bp, &remain); if (kret) goto cleanup; context->default_realm[ibuf] = '\0'; } /* Get the number of in_tkt_ktypes */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->in_tkt_ktype_count = (int) ibuf; context->in_tkt_ktypes = (krb5_enctype *) MALLOC(sizeof(krb5_enctype) * (context->in_tkt_ktype_count+1)); if (!context->in_tkt_ktypes) { kret = ENOMEM; goto cleanup; } (void) memset(context->in_tkt_ktypes, 0, (sizeof(krb5_enctype) * (context->in_tkt_ktype_count + 1))); for (i=0; iin_tkt_ktype_count; i++) { if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->in_tkt_ktypes[i] = (krb5_enctype) ibuf; } /* Get the number of tgs_ktypes */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->tgs_ktype_count = (int) ibuf; context->tgs_ktypes = (krb5_enctype *) MALLOC(sizeof(krb5_enctype) * (context->tgs_ktype_count+1)); if (!context->tgs_ktypes) { kret = ENOMEM; goto cleanup; } (void) memset(context->tgs_ktypes, 0, (sizeof(krb5_enctype) * (context->tgs_ktype_count + 1))); for (i=0; itgs_ktype_count; i++) { if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->tgs_ktypes[i] = (krb5_enctype) ibuf; } /* Allowable checksum */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->clockskew = (krb5_deltat) ibuf; /* kdc_req_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->kdc_req_sumtype = (krb5_cksumtype) ibuf; /* default ap_req_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->default_ap_req_sumtype = (krb5_cksumtype) ibuf; /* default_safe_sumtype */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->default_safe_sumtype = (krb5_cksumtype) ibuf; /* kdc_default_options */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->kdc_default_options = (krb5_flags) ibuf; /* library_options */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->library_options = (krb5_flags) ibuf; /* profile_secure */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->profile_secure = (krb5_boolean) ibuf; /* fcc_default_format */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->fcc_default_format = (int) ibuf; /* scc_default_format */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; context->scc_default_format = (int) ibuf; /* Attempt to read in the os_context. It's an array now, but we still treat it in most places as a separate object with a pointer. */ { krb5_os_context osp = 0; kret = krb5_internalize_opaque(kcontext, KV5M_OS_CONTEXT, (krb5_pointer *) &osp, &bp, &remain); if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; /* Put the newly allocated data into the krb5_context structure where we're really keeping it these days. */ if (osp) *context->os_context = *osp; free(osp); } /* Attempt to read in the db_context */ kret = krb5_internalize_opaque(kcontext, KV5M_DB_CONTEXT, (krb5_pointer *) &context->db_context, &bp, &remain); if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; #ifndef _KERNEL /* Attempt to read in the profile */ kret = krb5_internalize_opaque(kcontext, PROF_MAGIC_PROFILE, (krb5_pointer *) &context->profile, &bp, &remain); #endif if (kret && (kret != EINVAL) && (kret != ENOENT)) goto cleanup; /* Finally, find the trailer */ if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) goto cleanup; if (ibuf != KV5M_CONTEXT) { kret = EINVAL; goto cleanup; } context->magic = KV5M_CONTEXT; *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) context; return 0; cleanup: if (context) krb5_free_context(context); return(kret); } /* * krb5_oscontext_size() - Determine the size required to externalize * the krb5_os_context. */ /*ARGSUSED*/ static krb5_error_code krb5_oscontext_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { /* * We need five 32-bit integers: * two for header and trailer * one each for time_offset, usec_offset and os_flags */ *sizep += (5*sizeof(krb5_int32)); return(0); } /* * krb5_oscontext_externalize() - Externalize the krb5_os_context. */ static krb5_error_code krb5_oscontext_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_os_context os_ctx; size_t required; krb5_octet *bp; size_t remain; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; if ((os_ctx = (krb5_os_context) arg)) { kret = ENOMEM; if (!krb5_oscontext_size(kcontext, arg, &required) && (required <= remain)) { (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain); (void) krb5_ser_pack_int32(os_ctx->time_offset, &bp, &remain); (void) krb5_ser_pack_int32(os_ctx->usec_offset, &bp, &remain); (void) krb5_ser_pack_int32(os_ctx->os_flags, &bp, &remain); (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain); /* Handle any other OS context here */ kret = 0; if (!kret) { *buffer = bp; *lenremain = remain; } } } return(kret); } /* * krb5_oscontext_internalize() - Internalize the krb5_os_context. */ /*ARGSUSED*/ static krb5_error_code krb5_oscontext_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_os_context os_ctx; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; kret = EINVAL; os_ctx = (krb5_os_context) NULL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_OS_CONTEXT) { kret = ENOMEM; /* Get memory for the context */ if ((os_ctx = (krb5_os_context) MALLOC(sizeof(struct _krb5_os_context))) && (remain >= 4*sizeof(krb5_int32))) { (void) memset(os_ctx, 0, sizeof(struct _krb5_os_context)); os_ctx->magic = KV5M_OS_CONTEXT; /* Read out our context */ (void) krb5_ser_unpack_int32(&os_ctx->time_offset, &bp, &remain); (void) krb5_ser_unpack_int32(&os_ctx->usec_offset, &bp, &remain); (void) krb5_ser_unpack_int32(&os_ctx->os_flags, &bp, &remain); (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (ibuf == KV5M_OS_CONTEXT) { os_ctx->magic = KV5M_OS_CONTEXT; kret = 0; *buffer = bp; *lenremain = remain; } else kret = EINVAL; } } if (!kret) { *argp = (krb5_pointer) os_ctx; } else { if (os_ctx) FREE(os_ctx, sizeof(struct _krb5_os_context)); } return(kret); } /* * Register the context serializers. */ krb5_error_code KRB5_CALLCONV krb5_ser_context_init(krb5_context kcontext) { krb5_error_code kret; kret = krb5_register_serializer(kcontext, &krb5_context_ser_entry); if (!kret) kret = krb5_register_serializer(kcontext, &krb5_oscontext_ser_entry); /* Profile nformation need not be serialzied when we are importing the * context into kernel. Besides the function pointers to file access * routines can't be used in the kernel. * Any info needed from the profile is already a part of the * exported context obviating the need for importer to know about * profile config files. */ #ifndef _KERNEL if (!kret) kret = krb5_register_serializer(kcontext, &krb5_profile_ser_entry); #endif return(kret); } /* * lib/krb5/krb/ser_key.c * * Copyright 1995 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. 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. * */ /* * ser_key.c - Serialize a krb5_keyblock structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_keyblock: * krb5_keyblock_size(); * krb5_keyblock_externalize(); * krb5_keyblock_internalize(); */ static krb5_error_code krb5_keyblock_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_keyblock_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_keyblock_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_keyblock_ser_entry = { KV5M_KEYBLOCK, /* Type */ krb5_keyblock_size, /* Sizer routine */ krb5_keyblock_externalize, /* Externalize routine */ krb5_keyblock_internalize /* Internalize routine */ }; /* * krb5_keyblock_size() - Determine the size required to externalize * the krb5_keyblock. */ /*ARGSUSED*/ static krb5_error_code krb5_keyblock_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_keyblock *keyblock; /* * krb5_keyblock requires: * krb5_int32 for KV5M_KEYBLOCK * krb5_int32 for enctype * krb5_int32 for length * keyblock->length for contents * krb5_int32 for KV5M_KEYBLOCK */ kret = EINVAL; /* Solaris Kerberos */ keyblock = (krb5_keyblock *) arg; if (keyblock) { *sizep += (sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + sizeof(krb5_int32) + (size_t) keyblock->length); kret = 0; } return(kret); } /* * krb5_keyblock_externalize() - Externalize the krb5_keyblock. */ static krb5_error_code krb5_keyblock_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_keyblock *keyblock; size_t required; krb5_octet *bp; size_t remain; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ keyblock = (krb5_keyblock *) arg; if (keyblock) { kret = ENOMEM; if (!krb5_keyblock_size(kcontext, arg, &required) && (required <= remain)) { /* Our identifier */ (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain); /* Our enctype */ (void) krb5_ser_pack_int32((krb5_int32) keyblock->enctype, &bp, &remain); /* Our length */ (void) krb5_ser_pack_int32((krb5_int32) keyblock->length, &bp, &remain); /* Our contents */ (void) krb5_ser_pack_bytes(keyblock->contents, (size_t) keyblock->length, &bp, &remain); /* Finally, our trailer */ (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain); kret = 0; *buffer = bp; *lenremain = remain; } } return(kret); } /* * krb5_keyblock_internalize() - Internalize the krb5_keyblock. */ /*ARGSUSED*/ static krb5_error_code krb5_keyblock_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_keyblock *keyblock; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_KEYBLOCK) { kret = ENOMEM; /* Get a keyblock */ if ((remain >= (3*sizeof(krb5_int32))) && (keyblock = (krb5_keyblock *) MALLOC(sizeof(krb5_keyblock)))) { (void) memset(keyblock, 0, sizeof(krb5_keyblock)); /* Get the enctype */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); keyblock->enctype = (krb5_enctype) ibuf; /* Get the length */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); keyblock->length = (int) ibuf; /* Get the string */ /* Solaris Kerberos */ keyblock->contents = (krb5_octet *) MALLOC((size_t) (ibuf)); if ((keyblock->contents)&& !(kret = krb5_ser_unpack_bytes(keyblock->contents, (size_t) ibuf, &bp, &remain))) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf == KV5M_KEYBLOCK)) { kret = 0; *buffer = bp; *lenremain = remain; keyblock->magic = KV5M_KEYBLOCK; *argp = (krb5_pointer) keyblock; } else kret = EINVAL; } if (kret) { if (keyblock->contents) FREE(keyblock->contents, keyblock->length); FREE(keyblock, sizeof(krb5_keyblock)); } } } return(kret); } /* * Register the keyblock serializer. */ krb5_error_code krb5_ser_keyblock_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_keyblock_ser_entry)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/ser_princ.c * * Copyright 1995 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. * */ /* * ser_princ.c - Serialize a krb5_principal structure. */ #include "k5-int.h" #include "int-proto.h" /* * Routines to deal with externalizing the krb5_principal: * krb5_principal_size(); * krb5_principal_externalize(); * krb5_principal_internalize(); */ static krb5_error_code krb5_principal_size (krb5_context, krb5_pointer, size_t *); static krb5_error_code krb5_principal_externalize (krb5_context, krb5_pointer, krb5_octet **, size_t *); static krb5_error_code krb5_principal_internalize (krb5_context,krb5_pointer *, krb5_octet **, size_t *); /* Local data */ static const krb5_ser_entry krb5_principal_ser_entry = { KV5M_PRINCIPAL, /* Type */ krb5_principal_size, /* Sizer routine */ krb5_principal_externalize, /* Externalize routine */ krb5_principal_internalize /* Internalize routine */ }; /* * krb5_principal_size() - Determine the size required to externalize * the krb5_principal. */ static krb5_error_code krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_principal principal; char *fname; /* * krb5_principal requires: * krb5_int32 for KV5M_PRINCIPAL * krb5_int32 for flattened name size * strlen(name) for name. * krb5_int32 for KV5M_PRINCIPAL */ kret = EINVAL; /* Solaris Kerberos */ principal = (krb5_principal) arg; if ((principal) && !(kret = krb5_unparse_name(kcontext, principal, &fname))) { *sizep += (3*sizeof(krb5_int32)) + strlen(fname); /* Solaris Kerberos */ krb5_xfree_wrap(fname, strlen(fname) + 1); } return(kret); } /* * krb5_principal_externalize() - Externalize the krb5_principal. */ static krb5_error_code krb5_principal_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_principal principal; size_t required; krb5_octet *bp; size_t remain; char *fname; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Solaris Kerberos */ principal = (krb5_principal) arg; if (principal) { kret = ENOMEM; if (!krb5_principal_size(kcontext, arg, &required) && (required <= remain)) { if (!(kret = krb5_unparse_name(kcontext, principal, &fname))) { (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) strlen(fname), &bp, &remain); (void) krb5_ser_pack_bytes((krb5_octet *) fname, strlen(fname), &bp, &remain); (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); *buffer = bp; *lenremain = remain; /* Solaris Kerberos */ krb5_xfree_wrap(fname, strlen(fname) + 1); } } } return(kret); } /* * krb5_principal_internalize() - Internalize the krb5_principal. */ static krb5_error_code krb5_principal_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_principal principal; krb5_int32 ibuf; krb5_octet *bp; size_t remain; char *tmpname; /* Solaris Kerberos */ int tmpsize; bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KV5M_PRINCIPAL) { kret = ENOMEM; /* See if we have enough data for the length */ if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { /* Get the string */ /* Solaris Kerberos */ tmpsize = ibuf+1; tmpname = (char *) MALLOC(tmpsize); if ((tmpname) && !(kret = krb5_ser_unpack_bytes((krb5_octet *) tmpname, (size_t) ibuf, &bp, &remain))) { tmpname[ibuf] = '\0'; /* Parse the name to a principal structure */ principal = (krb5_principal) NULL; kret = krb5_parse_name(kcontext, tmpname, &principal); if (!kret) { kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && (ibuf == KV5M_PRINCIPAL)) { *buffer = bp; *lenremain = remain; *argp = principal; } else kret = EINVAL; } if (kret && principal) krb5_free_principal(kcontext, principal); /* Solaris Kerberos */ FREE(tmpname,tmpsize); } } } return(kret); } /* * Register the context serializer. */ krb5_error_code krb5_ser_principal_init(krb5_context kcontext) { return(krb5_register_serializer(kcontext, &krb5_principal_ser_entry)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/serialize.c * * Copyright 1995 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. * */ /* * Base routines to deal with serialization of Kerberos metadata. */ #include "k5-int.h" /* Solaris Kerberos */ #include #include #include /* * krb5_find_serializer() - See if a particular type is registered. */ krb5_ser_handle krb5_find_serializer(krb5_context kcontext, krb5_magic odtype) { krb5_ser_handle res; krb5_ser_handle sctx; int i; res = (krb5_ser_handle) NULL; sctx = (krb5_ser_handle) kcontext->ser_ctx; for (i=0; iser_ctx_count; i++) { if (sctx[i].odtype == odtype) { res = &sctx[i]; break; } } return(res); } /* * krb5_register_serializer() - Register a particular serializer. */ krb5_error_code krb5_register_serializer(krb5_context kcontext, const krb5_ser_entry *entry) { krb5_error_code kret; krb5_ser_handle stable; kret = 0; /* See if it's already there, if so, we're good to go. */ if (!(stable = krb5_find_serializer(kcontext, entry->odtype))) { /* * Can't find our type. Create a new entry. */ if ((stable = (krb5_ser_handle) MALLOC(sizeof(krb5_ser_entry) * (kcontext->ser_ctx_count+1)))) { /* Copy in old table */ if (kcontext->ser_ctx_count) (void) memcpy((void*)stable, kcontext->ser_ctx, sizeof(krb5_ser_entry) * kcontext->ser_ctx_count); /* Copy in new entry */ (void) memcpy((void*)&stable[kcontext->ser_ctx_count], entry, sizeof(krb5_ser_entry)); if (kcontext->ser_ctx) krb5_xfree_wrap(kcontext->ser_ctx, sizeof(krb5_ser_entry) * (kcontext->ser_ctx_count)); kcontext->ser_ctx = (void *) stable; kcontext->ser_ctx_count++; } else kret = ENOMEM; } else (void) memcpy((void*)stable, entry, sizeof(krb5_ser_entry)); return(kret); } /* * krb5_size_opaque() - Determine the size necessary to serialize a given * piece of opaque data. */ krb5_error_code KRB5_CALLCONV krb5_size_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_ser_handle shandle; kret = ENOENT; /* See if the type is supported, if so, do it */ if ((shandle = krb5_find_serializer(kcontext, odtype))) kret = (shandle->sizer) ? (*shandle->sizer)(kcontext, arg, sizep) : 0; return(kret); } /* * krb5_externalize_opaque() - Externalize a piece of opaque data. */ krb5_error_code KRB5_CALLCONV krb5_externalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep) { krb5_error_code kret; krb5_ser_handle shandle; kret = ENOENT; /* See if the type is supported, if so, do it */ if ((shandle = krb5_find_serializer(kcontext, odtype))) kret = (shandle->externalizer) ? (*shandle->externalizer)(kcontext, arg, bufpp, sizep) : 0; return(kret); } /* * Externalize a piece of arbitrary data. */ krb5_error_code krb5_externalize_data(krb5_context kcontext, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep) { krb5_error_code kret; krb5_magic *mp; krb5_octet *buffer, *bp; size_t bufsize, bsize; mp = (krb5_magic *) arg; bufsize = 0; if (!(kret = krb5_size_opaque(kcontext, *mp, arg, &bufsize))) { if ((buffer = (krb5_octet *) MALLOC(bufsize))) { bp = buffer; bsize = bufsize; if (!(kret = krb5_externalize_opaque(kcontext, *mp, arg, &bp, &bsize))) { if (bsize != 0) bufsize -= bsize; *bufpp = buffer; *sizep = bufsize; } } else kret = ENOMEM; } return(kret); } /* * krb5_internalize_opaque() - Convert external representation into a data * structure. */ krb5_error_code KRB5_CALLCONV krb5_internalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer *argp, krb5_octet **bufpp, size_t *sizep) { krb5_error_code kret; krb5_ser_handle shandle; kret = ENOENT; /* See if the type is supported, if so, do it */ if ((shandle = krb5_find_serializer(kcontext, odtype))) kret = (shandle->internalizer) ? (*shandle->internalizer)(kcontext, argp, bufpp, sizep) : 0; return(kret); } /* * krb5_ser_pack_int32() - Pack a 4-byte integer if space is available. * Update buffer pointer and remaining space. */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_int32(krb5_int32 iarg, krb5_octet **bufp, size_t *remainp) { if (*remainp >= sizeof(krb5_int32)) { (*bufp)[0] = (krb5_octet) ((iarg >> 24) & 0xff); (*bufp)[1] = (krb5_octet) ((iarg >> 16) & 0xff); (*bufp)[2] = (krb5_octet) ((iarg >> 8) & 0xff); (*bufp)[3] = (krb5_octet) (iarg & 0xff); *bufp += sizeof(krb5_int32); *remainp -= sizeof(krb5_int32); return(0); } else return(ENOMEM); } /* * krb5_ser_pack_int64() - Pack an 8-byte integer if space is available. * Update buffer pointer and remaining space. */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_int64(krb5_int64 iarg, krb5_octet **bufp, size_t *remainp) { if (*remainp >= sizeof(krb5_int64)) { store_64_be(iarg, (unsigned char *)*bufp); *bufp += sizeof(krb5_int64); *remainp -= sizeof(krb5_int64); return(0); } else return(ENOMEM); } /* * krb5_ser_pack_bytes() - Pack a string of bytes. */ krb5_error_code KRB5_CALLCONV krb5_ser_pack_bytes(krb5_octet *ostring, size_t osize, krb5_octet **bufp, size_t *remainp) { if (*remainp >= osize) { (void) memcpy(*bufp, ostring, osize); *bufp += osize; *remainp -= osize; return(0); } else return(ENOMEM); } /* * krb5_ser_unpack_int32() - Unpack a 4-byte integer if it's there. */ krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int32(krb5_int32 *intp, krb5_octet **bufp, size_t *remainp) { if (*remainp >= sizeof(krb5_int32)) { *intp = (((krb5_int32) ((unsigned char) (*bufp)[0]) << 24) | ((krb5_int32) ((unsigned char) (*bufp)[1]) << 16) | ((krb5_int32) ((unsigned char) (*bufp)[2]) << 8) | ((krb5_int32) ((unsigned char) (*bufp)[3]))); *bufp += sizeof(krb5_int32); *remainp -= sizeof(krb5_int32); return(0); } else return(ENOMEM); } /* * krb5_ser_unpack_int64() - Unpack an 8-byte integer if it's there. */ krb5_error_code KRB5_CALLCONV krb5_ser_unpack_int64(krb5_int64 *intp, krb5_octet **bufp, size_t *remainp) { if (*remainp >= sizeof(krb5_int64)) { *intp = load_64_be((unsigned char *)*bufp); *bufp += sizeof(krb5_int64); *remainp -= sizeof(krb5_int64); return(0); } else return(ENOMEM); } /* * krb5_ser_unpack_bytes() - Unpack a byte string if it's there. */ krb5_error_code KRB5_CALLCONV krb5_ser_unpack_bytes(krb5_octet *istring, size_t isize, krb5_octet **bufp, size_t *remainp) { if (*remainp >= isize) { (void) memcpy(istring, *bufp, isize); *bufp += isize; *remainp -= isize; return(0); } else return(ENOMEM); } /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/krb/unparse.c * * Copyright 1990, 2008 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * * krb5_unparse_name() routine * * Rewritten by Theodore Ts'o to properly unparse principal names * which have the component or realm separator as part of one of their * components. */ #include "k5-int.h" #ifndef _KERNEL #include #endif /* * SUNW17PACresync / Solaris Kerberos * This realloc works for both Solaris kernel and user space. */ void * krb5int_realloc( void *oldp, size_t new_size, size_t old_size) { #ifdef _KERNEL char *newp = MALLOC(new_size); bcopy(oldp, newp, old_size < new_size ? old_size : new_size); FREE(oldp, old_size); return (newp); #else return (realloc(oldp, new_size)); #endif } /* * converts the multi-part principal format used in the protocols to a * single-string representation of the name. * * The name returned is in allocated storage and should be freed by * the caller when finished. * * Conventions: / is used to separate components; @ is used to * separate the realm from the rest of the name. If '/', '@', or '\0' * appear in any the component, they will be representing using * backslash encoding. ("\/", "\@", or '\0', respectively) * * returns error * KRB_PARSE_MALFORMED principal is invalid (does not contain * at least 2 components) * also returns system errors * ENOMEM unable to allocate memory for string */ #define REALM_SEP '@' #define COMPONENT_SEP '/' static int component_length_quoted(const krb5_data *src, int flags) { const char *cp = src->data; int length = src->length; int j; int size = length; if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) { int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) && !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT); for (j = 0; j < length; j++,cp++) if ((!no_realm && *cp == REALM_SEP) || *cp == COMPONENT_SEP || *cp == '\0' || *cp == '\\' || *cp == '\t' || *cp == '\n' || *cp == '\b') size++; } return size; } static int copy_component_quoting(char *dest, const krb5_data *src, int flags) { int j; const char *cp = src->data; char *q = dest; int length = src->length; if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) { (void) memcpy(dest, src->data, src->length); return src->length; } for (j=0; j < length; j++,cp++) { int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) && !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT); switch (*cp) { case REALM_SEP: if (no_realm) { *q++ = *cp; break; } /* FALLTHROUGH */ case COMPONENT_SEP: case '\\': *q++ = '\\'; *q++ = *cp; break; case '\t': *q++ = '\\'; *q++ = 't'; break; case '\n': *q++ = '\\'; *q++ = 'n'; break; case '\b': *q++ = '\\'; *q++ = 'b'; break; #if 0 /* Heimdal escapes spaces in principal names upon unparsing */ case ' ': *q++ = '\\'; *q++ = ' '; break; #endif case '\0': *q++ = '\\'; *q++ = '0'; break; default: *q++ = *cp; } } /*LINTED*/ return q - dest; } static krb5_error_code /*LINTED*/ k5_unparse_name(krb5_context context, krb5_const_principal principal, int flags, char **name, unsigned int *size) { #if 0 /* SUNW17PACresync - lint - cp/length not used */ char *cp; int length; #endif char *q; int i; krb5_int32 nelem; unsigned int totalsize = 0; #ifndef _KERNEL /* SUNW17PACresync - princ in kernel will always have realm */ char *default_realm = NULL; #endif krb5_error_code ret = 0; if (!principal || !name) return KRB5_PARSE_MALFORMED; #ifndef _KERNEL if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) { /* omit realm if local realm */ krb5_principal_data p; ret = krb5_get_default_realm(context, &default_realm); if (ret != 0) goto cleanup; krb5_princ_realm(context, &p)->length = strlen(default_realm); krb5_princ_realm(context, &p)->data = default_realm; if (krb5_realm_compare(context, &p, principal)) flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM; } #endif if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) { totalsize += component_length_quoted(krb5_princ_realm(context, principal), flags); totalsize++; /* This is for the separator */ } nelem = krb5_princ_size(context, principal); for (i = 0; i < (int) nelem; i++) { #if 0 /* SUNW17PACresync - lint - cp not used */ cp = krb5_princ_component(context, principal, i)->data; #endif totalsize += component_length_quoted(krb5_princ_component(context, principal, i), flags); totalsize++; /* This is for the separator */ } if (nelem == 0) totalsize++; /* * Allocate space for the ascii string; if space has been * provided, use it, realloc'ing it if necessary. * * We need only n-1 seperators for n components, but we need * an extra byte for the NUL at the end. */ if (size) { if (*name && (*size < totalsize)) { /* SUNW17PACresync - works for both kernel&user */ *name = krb5int_realloc(*name, totalsize, *size); } else { *name = MALLOC(totalsize); } *size = totalsize; } else { *name = MALLOC(totalsize); } if (!*name) { ret = ENOMEM; goto cleanup; } q = *name; for (i = 0; i < (int) nelem; i++) { #if 0 /* SUNW17PACresync - lint - cp/length not used */ cp = krb5_princ_component(context, principal, i)->data; length = krb5_princ_component(context, principal, i)->length; #endif q += copy_component_quoting(q, krb5_princ_component(context, principal, i), flags); *q++ = COMPONENT_SEP; } if (i > 0) q--; /* Back up last component separator */ if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) { *q++ = REALM_SEP; q += copy_component_quoting(q, krb5_princ_realm(context, principal), flags); } *q++ = '\0'; cleanup: #ifndef _KERNEL if (default_realm != NULL) krb5_free_default_realm(context, default_realm); #endif return ret; } krb5_error_code KRB5_CALLCONV krb5_unparse_name(krb5_context context, krb5_const_principal principal, register char **name) { if (name != NULL) /* name == NULL will return error from _ext */ *name = NULL; return k5_unparse_name(context, principal, 0, name, NULL); } krb5_error_code KRB5_CALLCONV krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, char **name, unsigned int *size) { return k5_unparse_name(context, principal, 0, name, size); } krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, int flags, char **name) { if (name != NULL) *name = NULL; return k5_unparse_name(context, principal, flags, name, NULL); } krb5_error_code KRB5_CALLCONV krb5_unparse_name_flags_ext(krb5_context context, krb5_const_principal principal, int flags, char **name, unsigned int *size) { return k5_unparse_name(context, principal, flags, name, size); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/crypto/os/c_ustime.c * * Copyright 1990,1991 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. * * * krb5_mstimeofday for BSD 4.3 */ #include "k5-int.h" #include "k5-thread.h" k5_mutex_t krb5int_us_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER; struct time_now { krb5_int32 sec, usec; }; #if defined(_WIN32) /* Microsoft Windows NT and 95 (32bit) */ /* This one works for WOW (Windows on Windows, ntvdm on Win-NT) */ #include #include #include static krb5_error_code get_time_now(struct time_now *n) { struct _timeb timeptr; _ftime(&timeptr); n->sec = timeptr.time; n->usec = timeptr.millitm * 1000; return 0; } #else /* Everybody else is UNIX, right? POSIX 1996 doesn't give us gettimeofday, but what real OS doesn't? */ static krb5_error_code get_time_now(struct time_now *n) { struct timeval tv; #ifdef _KERNEL timestruc_t now; gethrestime(&now); tv.tv_sec = now.tv_sec; tv.tv_usec = now.tv_nsec / (NANOSEC / MICROSEC); #else if (gettimeofday(&tv, (struct timezone *)0) == -1) return errno; #endif n->sec = tv.tv_sec; n->usec = tv.tv_usec; return 0; } #endif static struct time_now last_time; krb5_error_code krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds) { struct time_now now; krb5_error_code err; err = get_time_now(&now); if (err) return err; err = k5_mutex_lock(&krb5int_us_time_mutex); if (err) return err; /* Just guessing: If the number of seconds hasn't changed, yet the microseconds are moving backwards, we probably just got a third instance of returning the same clock value from the system, so the saved value was artificially incremented. On Windows, where we get millisecond accuracy currently, that's quite likely. On UNIX, it appears that we always get new microsecond values, so this case should never trigger. */ if ((now.sec == last_time.sec) && (now.usec <= last_time.usec)) { /* Same as last time??? */ now.usec = ++last_time.usec; if (now.usec >= 1000000) { ++now.sec; now.usec = 0; } /* For now, we're not worrying about the case of enough returns of the same value that we roll over now.sec, and the next call still gets the previous now.sec value. */ } last_time.sec = now.sec; /* Remember for next time */ last_time.usec = now.usec; (void) k5_mutex_unlock(&krb5int_us_time_mutex); *seconds = now.sec; *microseconds = now.usec; return 0; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/os/init_ctx.c * * Copyright 1994 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. * * krb5_init_contex() */ #define NEED_WINDOWS #include "k5-int.h" #ifndef _KERNEL #include "os-proto.h" #if 0 /* Solaris Kerberos */ #include "prof_int.h" /* XXX for profile_copy, not public yet */ #endif errcode_t KRB5_CALLCONV profile_copy (profile_t, profile_t *); #endif #ifdef USE_LOGIN_LIBRARY #include "KerberosLoginPrivate.h" #endif #if defined(_WIN32) #include static krb5_error_code get_from_windows_dir( char **pname ) { UINT size = GetWindowsDirectory(0, 0); *pname = malloc(size + 1 + strlen(DEFAULT_PROFILE_FILENAME) + 1); if (*pname) { GetWindowsDirectory(*pname, size); strcat(*pname, "\\"); strcat(*pname, DEFAULT_PROFILE_FILENAME); return 0; } else { return KRB5_CONFIG_CANTOPEN; } } static krb5_error_code get_from_module_dir( char **pname ) { const DWORD size = 1024; /* fixed buffer */ int found = 0; char *p; char *name; struct _stat s; *pname = 0; name = MALLOC(size); if (!name) return ENOMEM; if (!GetModuleFileName(GetModuleHandle("krb5_32"), name, size)) goto cleanup; p = name + strlen(name); while ((p >= name) && (*p != '\\') && (*p != '/')) p--; if (p < name) goto cleanup; p++; strncpy(p, DEFAULT_PROFILE_FILENAME, size - (p - name)); name[size - 1] = 0; found = !_stat(name, &s); cleanup: if (found) *pname = name; else if (name) FREE(name, size); return 0; } /* * get_from_registry * * This will find a profile in the registry. *pbuffer != 0 if we * found something. Make sure to free(*pbuffer) when done. It will * return an error code if there is an error the user should know * about. We maintain the invariant: return value != 0 => * *pbuffer == 0. */ static krb5_error_code get_from_registry( char** pbuffer, HKEY hBaseKey ) { HKEY hKey = 0; LONG rc = 0; DWORD size = 0; krb5_error_code retval = 0; const char *key_path = "Software\\MIT\\Kerberos5"; const char *value_name = "config"; /* a wannabe assertion */ if (!pbuffer) { /* * We have a programming error! For now, we segfault :) * There is no good mechanism to deal. */ } *pbuffer = 0; if ((rc = RegOpenKeyEx(hBaseKey, key_path, 0, KEY_QUERY_VALUE, &hKey)) != ERROR_SUCCESS) { /* not a real error */ goto cleanup; } rc = RegQueryValueEx(hKey, value_name, 0, 0, 0, &size); if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA)) { /* not a real error */ goto cleanup; } *pbuffer = MALLOC(size); if (!*pbuffer) { retval = ENOMEM; goto cleanup; } if ((rc = RegQueryValueEx(hKey, value_name, 0, 0, *pbuffer, &size)) != ERROR_SUCCESS) { /* * Let's not call it a real error in case it disappears, but * we need to free so that we say we did not find anything. */ FREE(*pbuffer, size); *pbuffer = 0; goto cleanup; } cleanup: if (hKey) RegCloseKey(hKey); if (retval && *pbuffer) { FREE(*pbuffer, size); /* Let's say we did not find anything: */ *pbuffer = 0; } return retval; } #endif /* _WIN32 */ #ifndef _KERNEL static void free_filespecs(profile_filespec_t *files) { char **cp; if (files == 0) return; for (cp = files; *cp; cp++) free(*cp); free(files); } /* This function is needed by KfM's KerberosPreferences API * because it needs to be able to specify "secure" */ krb5_error_code os_get_default_config_files(profile_filespec_t **pfiles, krb5_boolean secure) { profile_filespec_t* files; #if defined(_WIN32) krb5_error_code retval = 0; char *name = 0; if (!secure) { char *env = getenv("KRB5_CONFIG"); if (env) { name = malloc(strlen(env) + 1); if (!name) return ENOMEM; strcpy(name, env); } } if (!name && !secure) { /* HKCU */ retval = get_from_registry(&name, HKEY_CURRENT_USER); if (retval) return retval; } if (!name) { /* HKLM */ retval = get_from_registry(&name, HKEY_LOCAL_MACHINE); if (retval) return retval; } if (!name && !secure) { /* module dir */ retval = get_from_module_dir(&name); if (retval) return retval; } if (!name) { /* windows dir */ retval = get_from_windows_dir(&name); } if (retval) return retval; if (!name) return KRB5_CONFIG_CANTOPEN; /* should never happen */ files = malloc(2 * sizeof(char *)); files[0] = name; files[1] = 0; #else /* !_WIN32 */ char* filepath = 0; int n_entries, i; unsigned int ent_len; const char *s, *t; #ifdef USE_LOGIN_LIBRARY /* If __KLAllowHomeDirectoryAccess() == FALSE, we are probably trying to authenticate to a fileserver for the user's homedir. */ if (!__KLAllowHomeDirectoryAccess ()) secure = 1; #endif if (secure) { filepath = DEFAULT_SECURE_PROFILE_PATH; } else { filepath = getenv("KRB5_CONFIG"); if (!filepath) filepath = DEFAULT_PROFILE_PATH; } /* count the distinct filename components */ for(s = filepath, n_entries = 1; *s; s++) { if (*s == ':') n_entries++; } /* the array is NULL terminated */ files = (char**) MALLOC((n_entries+1) * sizeof(char*)); if (files == 0) return ENOMEM; /* measure, copy, and skip each one */ /*LINTED*/ for(s = filepath, i=0; (t = strchr(s, ':')) || (t=s+strlen(s)); s=t+1, i++) { ent_len = t-s; files[i] = (char*) malloc(ent_len + 1); if (files[i] == 0) { /* if malloc fails, free the ones that worked */ while(--i >= 0) free(files[i]); free(files); return ENOMEM; } strncpy(files[i], s, ent_len); files[i][ent_len] = 0; if (*t == 0) { i++; break; } } /* cap the array */ files[i] = 0; #endif /* !_WIN32 */ *pfiles = (profile_filespec_t *)files; return 0; } static krb5_error_code add_kdc_config_file(profile_filespec_t **pfiles) { char *file; size_t count; profile_filespec_t *newfiles; file = getenv(KDC_PROFILE_ENV); if (file == NULL) file = DEFAULT_KDC_PROFILE; for (count = 0; (*pfiles)[count]; count++) ; count += 2; newfiles = malloc(count * sizeof(*newfiles)); if (newfiles == NULL) return errno; memcpy(newfiles + 1, *pfiles, (count-1) * sizeof(*newfiles)); newfiles[0] = strdup(file); if (newfiles[0] == NULL) { int e = errno; free(newfiles); return e; } free(*pfiles); *pfiles = newfiles; return 0; } /* Set the profile paths in the context. If secure is set to TRUE then do not include user paths (from environment variables, etc). If kdc is TRUE, include kdc.conf from whereever we expect to find it. */ static krb5_error_code os_init_paths(krb5_context ctx, krb5_boolean kdc) { krb5_error_code retval = 0; profile_filespec_t *files = 0; krb5_boolean secure = ctx->profile_secure; #ifdef KRB5_DNS_LOOKUP ctx->profile_in_memory = 0; #endif /* KRB5_DNS_LOOKUP */ retval = os_get_default_config_files(&files, secure); if (retval == 0 && kdc) retval = add_kdc_config_file(&files); if (!retval) { retval = profile_init((const_profile_filespec_t *) files, &ctx->profile); #ifdef KRB5_DNS_LOOKUP /* if none of the filenames can be opened use an empty profile */ if (retval == ENOENT) { retval = profile_init(NULL, &ctx->profile); if (!retval) ctx->profile_in_memory = 1; } #endif /* KRB5_DNS_LOOKUP */ } if (files) free_filespecs(files); if (retval) ctx->profile = 0; if (retval == ENOENT) return KRB5_CONFIG_CANTOPEN; if ((retval == PROF_SECTION_NOTOP) || (retval == PROF_SECTION_SYNTAX) || (retval == PROF_RELATION_SYNTAX) || (retval == PROF_EXTRA_CBRACE) || (retval == PROF_MISSING_OBRACE)) return KRB5_CONFIG_BADFORMAT; return retval; } #endif /* !_KERNEL */ /*ARGSUSED1*/ krb5_error_code krb5_os_init_context(krb5_context ctx, krb5_boolean kdc) { krb5_os_context os_ctx; krb5_error_code retval = 0; #ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; #endif /* _WIN32 */ os_ctx = ctx->os_context; os_ctx->magic = KV5M_OS_CONTEXT; os_ctx->time_offset = 0; os_ctx->usec_offset = 0; os_ctx->os_flags = 0; os_ctx->default_ccname = 0; #ifndef _KERNEL ctx->vtbl = 0; PLUGIN_DIR_INIT(&ctx->libkrb5_plugins); PLUGIN_DIR_INIT(&ctx->preauth_plugins); ctx->preauth_context = NULL; retval = os_init_paths(ctx, kdc); /* * If there's an error in the profile, return an error. Just * ignoring the error is a Bad Thing (tm). */ if (!retval) { krb5_cc_set_default_name(ctx, NULL); #ifdef _WIN32 /* We initialize winsock to version 1.1 but * we do not care if we succeed or fail. */ wVersionRequested = 0x0101; WSAStartup (wVersionRequested, &wsaData); #endif /* _WIN32 */ } #endif return retval; } #ifndef _KERNEL krb5_error_code KRB5_CALLCONV krb5_get_profile (krb5_context ctx, profile_t *profile) { return profile_copy (ctx->profile, profile); } #endif #ifndef _KERNEL krb5_error_code krb5_set_config_files(krb5_context ctx, const char **filenames) { krb5_error_code retval; profile_t profile; retval = profile_init(filenames, &profile); if (retval) return retval; if (ctx->profile) profile_release(ctx->profile); ctx->profile = profile; return 0; } krb5_error_code KRB5_CALLCONV krb5_get_default_config_files(char ***pfilenames) { if (!pfilenames) return EINVAL; return os_get_default_config_files(pfilenames, FALSE); } void KRB5_CALLCONV krb5_free_config_files(char **filenames) { free_filespecs(filenames); } #endif /* _KERNEL */ #ifndef _KERNEL krb5_error_code krb5_secure_config_files(krb5_context ctx) { /* Obsolete interface; always return an error. This function should be removed next time a major version number change happens. */ krb5_error_code retval; if (ctx->profile) { profile_release(ctx->profile); ctx->profile = 0; } ctx->profile_secure = TRUE; retval = os_init_paths(ctx, FALSE); if (retval) return retval; return KRB5_OBSOLETE_FN; } #endif /* _KERNEL */ void krb5_os_free_context(krb5_context ctx) { krb5_os_context os_ctx; os_ctx = ctx->os_context; if (os_ctx->default_ccname) { FREE(os_ctx->default_ccname, strlen(os_ctx->default_ccname) + 1); os_ctx->default_ccname = 0; } os_ctx->magic = 0; #ifndef _KERNEL if (ctx->profile) { profile_release(ctx->profile); ctx->profile = 0; } if (ctx->preauth_context) { krb5_free_preauth_context(ctx); ctx->preauth_context = NULL; } krb5int_close_plugin_dirs (&ctx->preauth_plugins); krb5int_close_plugin_dirs (&ctx->libkrb5_plugins); #endif } #ifdef _WIN32 WSACleanup(); #endif /* _WIN32 */ /* * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include /* * Note, there is no memset() in kernel land. This code is a replacement for * use in the kerberos kernel mech. * As a performance enhancement, bzero is called if the fill pattern is 0. */ void * krb5_memset(void *sp1, int c, size_t n) { if (n > 0) { if (c == 0) { bzero(sp1, n); } else { unsigned char *sp = sp1; do { *sp++ = (unsigned char)c; } while (--n != 0); } } return (sp1); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/krb5/os/timeofday.c * * Copyright 1990 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. * * * libos: krb5_timeofday function for BSD 4.3 */ #include "k5-int.h" #ifdef _KERNEL #include #else #include #include #endif krb5_error_code KRB5_CALLCONV krb5_timeofday(krb5_context context, register krb5_timestamp *timeret) { krb5_os_context os_ctx = context->os_context; /* Solaris Kerberos */ krb5_int32 tval; if (os_ctx->os_flags & KRB5_OS_TOFFSET_TIME) { *timeret = os_ctx->time_offset; return 0; } { krb5_int32 usecs; krb5_error_code kret; if (kret = krb5_crypto_us_timeofday(&tval, &usecs)) return kret; } /* Solaris Kerberos */ if (tval == (krb5_int32) -1) #ifdef _KERNEL return 1; #else return (krb5_error_code) errno; #endif if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) tval += os_ctx->time_offset; *timeret = tval; return 0; } /* * lib/krb5/os/toffset.c * * Copyright 1995 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. * * These routines manipulates the time offset fields in the os context. */ #include "k5-int.h" /* * This routine takes the "real time" as input, and sets the time * offset field in the context structure so that the krb5 time * routines will return the correct time as corrected by difference * between the system time and the "real time" as passed to this * routine */ krb5_error_code KRB5_CALLCONV krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds) { krb5_os_context os_ctx = context->os_context; krb5_int32 sec, usec; krb5_error_code retval; retval = krb5_crypto_us_timeofday(&sec, &usec); if (retval) return retval; os_ctx->time_offset = seconds - sec; os_ctx->usec_offset = microseconds - usec; os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | KRB5_OS_TOFFSET_VALID); return 0; } /* * This routine sets the krb5 time routines so that they will return * the seconds and microseconds value as input to this function. This * is useful for running the krb5 routines through test suites */ krb5_error_code krb5_set_debugging_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds) { krb5_os_context os_ctx = context->os_context; os_ctx->time_offset = seconds; os_ctx->usec_offset = microseconds; os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_VALID) | KRB5_OS_TOFFSET_TIME); return 0; } /* * This routine turns off the time correction fields, so that the krb5 * routines return the "natural" time. */ krb5_error_code krb5_use_natural_time(krb5_context context) { krb5_os_context os_ctx = context->os_context; os_ctx->os_flags &= ~(KRB5_OS_TOFFSET_VALID|KRB5_OS_TOFFSET_TIME); return 0; } /* * This routine returns the current time offsets in use. */ krb5_error_code KRB5_CALLCONV krb5_get_time_offsets(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds) { krb5_os_context os_ctx = context->os_context; if (seconds) *seconds = os_ctx->time_offset; if (microseconds) *microseconds = os_ctx->usec_offset; return 0; } /* * This routine sets the time offsets directly. */ krb5_error_code krb5_set_time_offsets(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds) { krb5_os_context os_ctx = context->os_context; os_ctx->time_offset = seconds; os_ctx->usec_offset = microseconds; os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | KRB5_OS_TOFFSET_VALID); return 0; } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. * * A module for Kerberos V5 security mechanism. * */ #include #include #include #include #include #include #include #include #include /* mechglue wrappers */ static OM_uint32 k5glue_delete_sec_context (void *, OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ gss_buffer_t, /* output_token */ OM_uint32); static OM_uint32 k5glue_sign (void *, OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* qop_req */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* message_token */ OM_uint32); static OM_uint32 k5glue_verify (void *, OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* message_buffer */ gss_buffer_t, /* token_buffer */ int *, /* qop_state */ OM_uint32); static OM_uint32 k5glue_seal (void *, OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ int, /* conf_req_flag */ int, /* qop_req */ gss_buffer_t, /* input_message_buffer */ int *, /* conf_state */ gss_buffer_t, /* output_message_buffer */ OM_uint32); static OM_uint32 k5glue_unseal (void *, OM_uint32 *, /* minor_status */ gss_ctx_id_t, /* context_handle */ gss_buffer_t, /* input_message_buffer */ gss_buffer_t, /* output_message_buffer */ int *, /* conf_state */ int *, /* qop_state */ OM_uint32); static OM_uint32 k5glue_import_sec_context (void *, OM_uint32 *, /* minor_status */ gss_buffer_t, /* interprocess_token */ gss_ctx_id_t *); /* context_handle */ static struct gss_config krb5_mechanism = {{9, "\052\206\110\206\367\022\001\002\002"}, NULL, /* context */ NULL, /* next */ TRUE, /* uses_kmod */ k5glue_unseal, k5glue_delete_sec_context, k5glue_seal, k5glue_import_sec_context, k5glue_sign, k5glue_verify, }; static gss_mechanism gss_mech_initialize() { return (&krb5_mechanism); } /* * Module linkage information for the kernel. */ extern struct mod_ops mod_miscops; static struct modlmisc modlmisc = { &mod_miscops, "Krb5 GSS mechanism" }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modlmisc, NULL }; static int krb5_fini_code = EBUSY; int _init() { int retval; gss_mechanism mech, tmp; if ((retval = mod_install(&modlinkage)) != 0) return (retval); mech = gss_mech_initialize(); mutex_enter(&__kgss_mech_lock); tmp = __kgss_get_mechanism(&mech->mech_type); if (tmp != NULL) { KRB5_LOG0(KRB5_INFO, "KRB5 GSS mechanism: mechanism already in table.\n"); if (tmp->uses_kmod == TRUE) { KRB5_LOG0(KRB5_INFO, "KRB5 GSS mechanism: mechanism " "table supports kernel operations!\n"); } /* * keep us loaded, but let us be unloadable. This * will give the developer time to trouble shoot */ krb5_fini_code = 0; } else { __kgss_add_mechanism(mech); ASSERT(__kgss_get_mechanism(&mech->mech_type) == mech); } mutex_exit(&__kgss_mech_lock); return (0); } int _fini() { int ret = krb5_fini_code; if (ret == 0) { ret = (mod_remove(&modlinkage)); } return (ret); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } /* ARGSUSED */ static OM_uint32 k5glue_delete_sec_context(ctx, minor_status, context_handle, output_token, gssd_ctx_verifier) void *ctx; OM_uint32 *minor_status; gss_ctx_id_t *context_handle; gss_buffer_t output_token; OM_uint32 gssd_ctx_verifier; { return (krb5_gss_delete_sec_context(minor_status, context_handle, output_token, gssd_ctx_verifier)); } /* V2 */ /* ARGSUSED */ static OM_uint32 k5glue_import_sec_context(ctx, minor_status, interprocess_token, context_handle) void *ctx; OM_uint32 *minor_status; gss_buffer_t interprocess_token; gss_ctx_id_t *context_handle; { return (krb5_gss_import_sec_context(minor_status, interprocess_token, context_handle)); } /* V1 only */ /* ARGSUSED */ static OM_uint32 k5glue_seal(ctx, minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, gssd_ctx_verifier) void *ctx; OM_uint32 *minor_status; gss_ctx_id_t context_handle; int conf_req_flag; int qop_req; gss_buffer_t input_message_buffer; int *conf_state; gss_buffer_t output_message_buffer; OM_uint32 gssd_ctx_verifier; { return (krb5_gss_seal(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, gssd_ctx_verifier)); } /* ARGSUSED */ static OM_uint32 k5glue_sign(ctx, minor_status, context_handle, qop_req, message_buffer, message_token, gssd_ctx_verifier) void *ctx; OM_uint32 *minor_status; gss_ctx_id_t context_handle; int qop_req; gss_buffer_t message_buffer; gss_buffer_t message_token; OM_uint32 gssd_ctx_verifier; { return (krb5_gss_sign(minor_status, context_handle, qop_req, message_buffer, message_token, gssd_ctx_verifier)); } /* ARGSUSED */ static OM_uint32 k5glue_unseal(ctx, minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state, gssd_ctx_verifier) void *ctx; OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t input_message_buffer; gss_buffer_t output_message_buffer; int *conf_state; int *qop_state; OM_uint32 gssd_ctx_verifier; { return (krb5_gss_unseal(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state, gssd_ctx_verifier)); } /* V1 only */ /* ARGSUSED */ static OM_uint32 k5glue_verify(ctx, minor_status, context_handle, message_buffer, token_buffer, qop_state, gssd_ctx_verifier) void *ctx; OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t message_buffer; gss_buffer_t token_buffer; int *qop_state; OM_uint32 gssd_ctx_verifier; { return (krb5_gss_verify(minor_status, context_handle, message_buffer, token_buffer, qop_state, gssd_ctx_verifier)); } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" #include "mglueP.h" /* SUNW15resync - for KGSS_ macros */ /* * $Id: delete_sec_context.c 18396 2006-07-25 20:29:43Z lxs $ */ #ifdef _KERNEL /* SUNW15resync - todo - unify these kernel rel oid funcs with user spc ones */ OM_uint32 krb5_gss_internal_release_oid(minor_status, oid) OM_uint32 *minor_status; gss_OID *oid; { /* * This function only knows how to release internal OIDs. It will * return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize. */ if ((*oid != gss_mech_krb5) && (*oid != gss_mech_krb5_old) && (*oid != gss_mech_krb5_wrong) && (*oid != gss_nt_krb5_name) && (*oid != gss_nt_krb5_principal)) { /* We don't know about this OID */ return(GSS_S_CONTINUE_NEEDED); } else { *oid = GSS_C_NO_OID; *minor_status = 0; return(GSS_S_COMPLETE); } } OM_uint32 generic_gss_release_oid(minor_status, oid) OM_uint32 *minor_status; gss_OID *oid; { if (minor_status) *minor_status = 0; if (*oid == GSS_C_NO_OID) return(GSS_S_COMPLETE); if ((*oid != GSS_C_NT_USER_NAME) && (*oid != GSS_C_NT_MACHINE_UID_NAME) && (*oid != GSS_C_NT_STRING_UID_NAME) && (*oid != GSS_C_NT_HOSTBASED_SERVICE) && (*oid != GSS_C_NT_ANONYMOUS) && (*oid != GSS_C_NT_EXPORT_NAME) && (*oid != gss_nt_service_name)) { FREE((*oid)->elements, (*oid)->length); FREE(*oid, sizeof(gss_OID_desc)); } *oid = GSS_C_NO_OID; return(GSS_S_COMPLETE); } OM_uint32 krb5_gss_release_oid(minor_status, oid) OM_uint32 *minor_status; gss_OID *oid; { if (krb5_gss_internal_release_oid(minor_status, oid) != GSS_S_COMPLETE) { /* Pawn it off on the generic routine */ return(generic_gss_release_oid(minor_status, oid)); } else { *oid = GSS_C_NO_OID; *minor_status = 0; return(GSS_S_COMPLETE); } } #endif /*ARGSUSED*/ OM_uint32 krb5_gss_delete_sec_context(minor_status, context_handle, output_token #ifdef _KERNEL , gssd_ctx_verifier #endif ) OM_uint32 *minor_status; gss_ctx_id_t *context_handle; gss_buffer_t output_token; #ifdef _KERNEL OM_uint32 gssd_ctx_verifier; #endif { krb5_context context; krb5_gss_ctx_id_rec *ctx; if (output_token) { output_token->length = 0; output_token->value = NULL; } /*SUPPRESS 29*/ if (*context_handle == GSS_C_NO_CONTEXT) { *minor_status = 0; return(GSS_S_COMPLETE); } /*SUPPRESS 29*/ /* 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_t) *context_handle; context = ctx->k5_context; /* construct a delete context token if necessary */ if (output_token) { OM_uint32 major; gss_buffer_desc empty; empty.length = 0; empty.value = NULL; if ((major = kg_seal(minor_status, *context_handle, 0, GSS_C_QOP_DEFAULT, &empty, NULL, output_token, KG_TOK_DEL_CTX))) { save_error_info(*minor_status, context); return(major); } } /* invalidate the context handle */ (void)kg_delete_ctx_id(*context_handle); /* free all the context state */ if (ctx->seqstate) g_order_free(&(ctx->seqstate)); if (ctx->enc) krb5_free_keyblock(context, ctx->enc); if (ctx->seq) krb5_free_keyblock(context, ctx->seq); if (ctx->here) krb5_free_principal(context, ctx->here); if (ctx->there) krb5_free_principal(context, ctx->there); if (ctx->subkey) krb5_free_keyblock(context, ctx->subkey); if (ctx->acceptor_subkey) krb5_free_keyblock(context, ctx->acceptor_subkey); /* We never import the auth_context into the kernel */ #ifndef _KERNEL if (ctx->auth_context) { if (ctx->cred_rcache) (void)krb5_auth_con_setrcache(context, ctx->auth_context, NULL); krb5_auth_con_free(context, ctx->auth_context); } #endif if (ctx->mech_used) (void) KGSS_RELEASE_OID(minor_status, &ctx->mech_used); if (ctx->authdata) krb5_free_authdata(context, ctx->authdata); if (ctx->k5_context) krb5_free_context(ctx->k5_context); /* Zero out context */ (void) memset(ctx, 0, sizeof(*ctx)); xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec)); /* zero the handle itself */ *context_handle = GSS_C_NO_CONTEXT; *minor_status = 0; return(GSS_S_COMPLETE); } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* * $Id: gssapi_krb5.c 18343 2006-07-19 18:14:01Z lxs $ */ /* For declaration of krb5_ser_context_init */ #include "k5-int.h" #include "gssapiP_krb5.h" #ifndef _KERNEL #include "gss_libinit.h" #endif /* * Solaris Kerberos * Kernel kgssd module debugging aid. The global variable "krb5_log" is a bit * mask which allows various types of log messages to be printed out. * * The log levels are defined in: * usr/src/uts/common/gssapi/mechs/krb5/include/k5-int.h * * Note, KRB5_LOG_LVL can be assigned via the make invocation. * See KRB5_DEFS in the various Makefiles. */ #ifdef KRB5_LOG_LVL /* set the log level to that specified */ u_int krb5_log = KRB5_LOG_LVL; #else /* default log level */ u_int krb5_log = 0; #endif /* KRB5_LOG_LVL */ /** exported constants defined in gssapi_krb5{,_nx}.h **/ /* these are bogus, but will compile */ /* * The OID of the draft krb5 mechanism, assigned by IETF, is: * iso(1) org(3) dod(5) internet(1) security(5) * kerberosv5(2) = 1.3.5.1.5.2 * The OID of the krb5_name type is: * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1 * The OID of the krb5_principal type is: * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2 * The OID of the proposed standard krb5 mechanism is: * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * krb5(2) = 1.2.840.113554.1.2.2 * The OID of the proposed standard krb5 v2 mechanism is: * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) * krb5v2(3) = 1.2.840.113554.1.2.3 * */ /* * Encoding rules: The first two values are encoded in one byte as 40 * * value1 + value2. Subsequent values are encoded base 128, most * significant digit first, with the high bit (\200) set on all octets * except the last in each value's encoding. */ const gss_OID_desc krb5_gss_oid_array[] = { /* this is the official, rfc-specified OID */ {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID}, /* this pre-RFC mech OID */ {GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID}, /* this is the unofficial, incorrect mech OID emitted by MS */ {GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID}, /* 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_wrong = krb5_gss_oid_array+2; const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+4; const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+5; const gss_OID_desc * const GSS_KRB5_NT_PRINCIPAL_NAME = krb5_gss_oid_array+4; static const gss_OID_set_desc oidsets[] = { {1, (gss_OID) krb5_gss_oid_array+0}, {1, (gss_OID) krb5_gss_oid_array+1}, {3, (gss_OID) krb5_gss_oid_array+0}, {1, (gss_OID) krb5_gss_oid_array+2}, {3, (gss_OID) krb5_gss_oid_array+0}, }; const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+0; const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+1; const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2; g_set kg_vdb = G_SET_INIT; /** default credential support */ #ifndef _KERNEL /* * init_sec_context() will explicitly re-acquire default credentials, * so handling the expiration/invalidation condition here isn't needed. */ OM_uint32 kg_get_defcred(minor_status, cred) OM_uint32 *minor_status; gss_cred_id_t *cred; { OM_uint32 major; if ((major = krb5_gss_acquire_cred(minor_status, (gss_name_t) NULL, GSS_C_INDEFINITE, GSS_C_NULL_OID_SET, GSS_C_INITIATE, cred, NULL, NULL)) && GSS_ERROR(major)) { return(major); } *minor_status = 0; return(GSS_S_COMPLETE); } OM_uint32 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status) { OM_uint32 err = 0; /* * Sync up the context ccache name with the GSSAPI ccache name. * If kg_ccache_name is NULL -- normal unless someone has called * gss_krb5_ccache_name() -- then the system default ccache will * be picked up and used by resetting the context default ccache. * This is needed for platforms which support multiple ccaches. */ if (!err) { /* if NULL, resets the context default ccache */ err = krb5_cc_set_default_name(context, (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME)); } *minor_status = err; return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } /* This function returns whether or not the caller set a cccache name. Used by * gss_acquire_cred to figure out if the caller wants to only look at this * ccache or search the cache collection for the desired name */ OM_uint32 kg_caller_provided_ccache_name (OM_uint32 *minor_status, int *out_caller_provided_name) { if (out_caller_provided_name) { *out_caller_provided_name = (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL); } *minor_status = 0; return GSS_S_COMPLETE; } OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status, const char **out_name) { const char *name = NULL; OM_uint32 err = 0; char *kg_ccache_name; kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME); if (kg_ccache_name != NULL) { name = strdup(kg_ccache_name); if (name == NULL) err = errno; } else { krb5_context context = NULL; /* Reset the context default ccache (see text above), and then retrieve it. */ err = krb5_gss_init_context(&context); if (!err) err = krb5_cc_set_default_name (context, NULL); if (!err) { name = krb5_cc_default_name(context); if (name) { name = strdup(name); if (name == NULL) err = ENOMEM; } } if (err && context) save_error_info(err, context); if (context) krb5_free_context(context); } if (!err) { if (out_name) { *out_name = name; } } *minor_status = err; return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; } OM_uint32 kg_set_ccache_name (OM_uint32 *minor_status, const char *name) { char *new_name = NULL; char *swap = NULL; char *kg_ccache_name; krb5_error_code kerr; if (name) { new_name = malloc(strlen(name) + 1); if (new_name == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } strcpy(new_name, name); } kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME); swap = kg_ccache_name; kg_ccache_name = new_name; new_name = swap; kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name); if (kerr != 0) { /* Can't store, so free up the storage. */ free(kg_ccache_name); /* ??? free(new_name); */ *minor_status = kerr; return GSS_S_FAILURE; } free (new_name); *minor_status = 0; return GSS_S_COMPLETE; } #define g_OID_prefix_equal(o1, o2) \ (((o1)->length >= (o2)->length) && \ (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0)) /* * gss_inquire_sec_context_by_oid() methods */ static struct { gss_OID_desc oid; OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); } krb5_gss_inquire_sec_context_by_oid_ops[] = { { {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID}, gss_krb5int_get_tkt_flags }, { {GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID}, gss_krb5int_extract_authz_data_from_sec_context }, { {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID}, gss_krb5int_inq_session_key }, { {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID}, gss_krb5int_export_lucid_sec_context }, { {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID}, gss_krb5int_extract_authtime_from_sec_context } }; OM_uint32 krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t *data_set) { krb5_gss_ctx_id_rec *ctx; size_t i; if (minor_status == NULL) return GSS_S_CALL_INACCESSIBLE_WRITE; *minor_status = 0; if (desired_object == GSS_C_NO_OID) return GSS_S_CALL_INACCESSIBLE_READ; if (data_set == NULL) return GSS_S_CALL_INACCESSIBLE_WRITE; *data_set = GSS_C_NO_BUFFER_SET; if (!kg_validate_ctx_id(context_handle)) return GSS_S_NO_CONTEXT; ctx = (krb5_gss_ctx_id_rec *) context_handle; if (!ctx->established) return GSS_S_NO_CONTEXT; for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/ sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) { if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) { return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status, context_handle, desired_object, data_set); } } *minor_status = EINVAL; return GSS_S_UNAVAILABLE; } #if 0 /* Solaris Kerberos - revisit for full 1.7/next resync */ MAKE_INIT_FUNCTION(gss_krb5int_lib_init); MAKE_FINI_FUNCTION(gss_krb5int_lib_fini); #endif OM_uint32 gss_krb5int_initialize_library (void) { #if 0 /* Solaris Kerberos - revisit for full 1.7/next resync */ #ifdef _GSS_STATIC_LINK return gssint_mechglue_initialize_library(); #else return CALL_INIT_FUNCTION(gss_krb5int_lib_init); #endif #endif return gssint_initialize_library(); } #endif /* !KERNEL */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * lib/gssapi/krb5/import_sec_context.c * * Copyright 1995,2004 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * */ /* * import_sec_context.c - Internalize the security context. */ #include "gssapiP_krb5.h" /* for serialization initialization functions */ #include "k5-int.h" #include "mglueP.h" /* SUNW15resync - for KGSS_ macros */ #ifdef _KERNEL extern OM_uint32 kgss_release_oid(OM_uint32 *, gss_OID *); #endif /* * Fix up the OID of the mechanism so that uses the static version of * the OID if possible. */ gss_OID krb5_gss_convert_static_mech_oid(oid) gss_OID oid; { const gss_OID_desc *p; OM_uint32 minor_status; for (p = krb5_gss_oid_array; p->length; p++) { if ((oid->length == p->length) && (memcmp(oid->elements, p->elements, p->length) == 0)) { (void) KGSS_RELEASE_OID(&minor_status, &oid); return (gss_OID) p; } } return oid; } krb5_error_code krb5_gss_ser_init (krb5_context context) { krb5_error_code code; static krb5_error_code (KRB5_CALLCONV *const fns[])(krb5_context) = { krb5_ser_auth_context_init, #ifndef _KERNEL krb5_ser_context_init, krb5_ser_ccache_init, krb5_ser_rcache_init, krb5_ser_keytab_init, #endif }; int i; for (i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) if ((code = (fns[i])(context)) != 0) return code; return 0; } OM_uint32 krb5_gss_import_sec_context(minor_status, interprocess_token, context_handle) OM_uint32 *minor_status; gss_buffer_t interprocess_token; gss_ctx_id_t *context_handle; { krb5_context context; krb5_error_code kret = 0; size_t blen; krb5_gss_ctx_id_t ctx; krb5_octet *ibp; /* This is a bit screwy. We create a krb5 context because we need one when calling the serialization code. However, one of the objects we're unpacking is a krb5 context, so when we finish, we can throw this one away. */ kret = KGSS_INIT_CONTEXT(&context); if (kret) { *minor_status = kret; return GSS_S_FAILURE; } kret = krb5_gss_ser_init(context); if (kret) { *minor_status = kret; save_error_info(*minor_status, context); krb5_free_context(context); return GSS_S_FAILURE; } /* Assume a tragic failure */ ctx = (krb5_gss_ctx_id_t) NULL; *minor_status = 0; /* Internalize the context */ ibp = (krb5_octet *) interprocess_token->value; blen = (size_t) interprocess_token->length; kret = kg_ctx_internalize(context, (krb5_pointer *) &ctx, &ibp, &blen); /* * SUNW15resync * * krb5_free_context(context); * Previous versions of MIT(1.2ish)/Solaris did not serialize the * k5_context but MIT 1.5 does. But we don't need all the userspace * junk in the kernel so we continue to not serialize it. * So we keep this context live here (see it's use in kg_ctx_internalize) * and it will get freed by delete_sec_context. */ if (kret) { *minor_status = (OM_uint32) kret; save_error_info(*minor_status, context); krb5_free_context(context); return(GSS_S_FAILURE); } /* intern the context handle */ if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) { (void)krb5_gss_delete_sec_context(minor_status, (gss_ctx_id_t *) &ctx, NULL #ifdef _KERNEL ,0 /* gssd_ctx_verifier */ #endif ); *minor_status = (OM_uint32) G_VALIDATE_FAILED; return(GSS_S_FAILURE); } ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); *context_handle = (gss_ctx_id_t) ctx; *minor_status = 0; return (GSS_S_COMPLETE); } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "gssapiP_krb5.h" #include static krb5_error_code make_seal_token_v1 (krb5_context context, krb5_keyblock *enc, krb5_keyblock *seq, gssint_uint64 *seqnum, int direction, gss_buffer_t text, gss_buffer_t token, int signalg, size_t cksum_size, int sealalg, int encrypt, int toktype, int bigend, gss_OID oid) { krb5_error_code code; size_t sumlen; char *data_ptr; krb5_data plaind; krb5_checksum md5cksum; krb5_checksum cksum; /* msglen contains the message length * we are signing/encrypting. tmsglen * contains the length of the message * we plan to write out to the token. * tlen is the length of the token * including header. */ unsigned conflen=0, tmsglen, tlen, msglen; unsigned char *t, *ptr; unsigned char *plain; unsigned char pad; krb5_keyusage sign_usage = KG_USAGE_SIGN; OM_uint32 seqnum32; /* Solaris Kerberos: check for recognized signalg and sealalg */ KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() start\n"); #ifdef _KERNEL /* * Because the ARCFOUR code bypasses the standard * crypto interfaces, we must make sure the kernel * crypto framework mechanism types are properly * initialized here. */ context->kef_cipher_mt = get_cipher_mech_type(context, seq); context->kef_hash_mt = get_hash_mech_type(context, seq); if ((code = init_key_kef(context->kef_cipher_mt, seq))) { return (code); } if ((code = init_key_kef(context->kef_cipher_mt, enc))) { return (code); } #endif /* _KERNEL */ /* create the token buffer */ /* Do we need confounder? */ if (encrypt || (!bigend && (toktype == KG_TOK_SEAL_MSG))) conflen = kg_confounder_size(context, enc); else conflen = 0; if (toktype == KG_TOK_SEAL_MSG) { switch (sealalg) { case SEAL_ALG_MICROSOFT_RC4: msglen = conflen + text->length+1; pad = 1; break; default: /* XXX knows that des block size is 8 */ msglen = (conflen+text->length+8)&(~7); pad = 8-(text->length%8); } tmsglen = msglen; } else { tmsglen = 0; msglen = text->length; pad = 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] = (unsigned char) (signalg & 0xff); ptr[1] = (unsigned char) ((signalg >> 8) & 0xff); /* 2..3 SEAL_ALG or Filler */ if ((toktype == KG_TOK_SEAL_MSG) && encrypt) { ptr[2] = (unsigned char) (sealalg & 0xff); ptr[3] = (unsigned char) ((sealalg >> 8) & 0xff); } 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 */ switch (signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_MD2_5: md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; break; case SGN_ALG_HMAC_SHA1_DES3_KD: md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; break; case SGN_ALG_HMAC_MD5: md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; if (toktype != KG_TOK_SEAL_MSG) sign_usage = 15; break; default: KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, error2 signalg=%d\n", signalg); #ifndef _KERNEL abort (); #else return (GSS_S_DEFECTIVE_TOKEN); #endif /* _KERNEL */ } code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); if (code) { KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, krb5_c_checksum_length() " "error code=%d\n", code); return(code); } md5cksum.length = sumlen; if ((plain = (unsigned char *) xmalloc(msglen ? msglen : 1)) == NULL) { xfree_wrap(t, tlen); return(ENOMEM); } if (conflen) { if ((code = kg_make_confounder(context, enc, plain))) { xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, " "kg_make_confounder() error code=%d\n", code); return(code); } } (void) memcpy(plain+conflen, text->value, text->length); if (pad) (void) memset(plain+conflen+text->length, pad, pad); /* compute the checksum */ /* 8 = head of token body as specified by mech spec */ if (! (data_ptr = (char *) xmalloc(8 + (bigend ? text->length : msglen)))) { xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); 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, msglen); plaind.length = 8 + (bigend ? text->length : msglen); plaind.data = data_ptr; code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq, sign_usage, &plaind, &md5cksum); xfree_wrap(data_ptr,8 + (bigend ? text->length : msglen)); if (code) { KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, " "krb5_c_make_checksum() error code=%d\n", code); xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); return(code); } 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_wrap(md5cksum.contents, md5cksum.length); xfree_wrap(t, tlen); KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_encrypt() " "error code=%d\n", code); return code; } cksum.length = cksum_size; cksum.contents = md5cksum.contents + 16 - cksum.length; (void) 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) { KRB5_LOG1(KRB5_ERR, "make_seal_token_v1() end, error " "md5cksum.length %u != " "cksum_size %u\n", (unsigned int)md5cksum.length, (unsigned int) cksum_size); #ifndef _KERNEL abort (); #else return (GSS_S_DEFECTIVE_TOKEN); #endif } (void) memcpy(ptr+14, md5cksum.contents, md5cksum.length); break; case SGN_ALG_HMAC_MD5: KRB5_LOG(KRB5_INFO, "make_seal_token_v1() cksum_size = %u", (unsigned int)cksum_size); (void) memcpy(ptr+14, md5cksum.contents, cksum_size); break; } xfree_wrap(md5cksum.contents, md5cksum.length); /* create the seq_num */ seqnum32 = (OM_uint32)(*seqnum & 0xFFFFFFFF); if ((code = kg_make_seq_num(context, seq, direction?0:0xff, seqnum32, ptr+14, ptr+6))) { xfree_wrap(t, tlen); KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_make_seq_num() " "error code=%d\n", code); return(code); } if (encrypt) { switch(sealalg) { case SEAL_ALG_MICROSOFT_RC4: { unsigned char bigend_seqnum[4]; krb5_keyblock *enc_key; int i; bigend_seqnum[0] = (*seqnum>>24) & 0xff; bigend_seqnum[1] = (*seqnum>>16) & 0xff; bigend_seqnum[2] = (*seqnum>>8) & 0xff; bigend_seqnum[3] = *seqnum & 0xff; code = krb5_copy_keyblock (context, enc, &enc_key); if (code) { xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); return(code); } for (i = 0; i <= 15; i++) ((char *) enc_key->contents)[i] ^=0xf0; code = kg_arcfour_docrypt (context, enc_key, 0, bigend_seqnum, 4, plain, tmsglen, ptr+14+cksum_size); krb5_free_keyblock (context, enc_key); if (code) { xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); return(code); } } break; default: if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL, (krb5_pointer) plain, (krb5_pointer) (ptr+cksum_size+14), tmsglen))) { xfree_wrap(plain, msglen ? msglen : 1); xfree_wrap(t, tlen); return(code); } } }else { if (tmsglen) (void) memcpy(ptr+14+cksum_size, plain, tmsglen); } xfree_wrap(plain, msglen ? msglen : 1); /* that's it. return the token */ (*seqnum)++; *seqnum &= (ulong_t)0xffffffffU; token->length = tlen; token->value = (void *) t; KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() end\n"); return(0); } /* if signonly is true, ignore conf_req, conf_state, and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ OM_uint32 kg_seal(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, toktype) 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; krb5_context context; KRB5_LOG0(KRB5_INFO, "kg_seal() start"); output_message_buffer->length = 0; output_message_buffer->value = NULL; /* Only default qop or matching established cryptosystem is allowed. There are NO EXTENSIONS to this set for AES and friends! The new spec says "just use 0". The old spec plus extensions would actually allow for certain non-zero values. Fix this to handle them later. */ if (qop_req != 0) { *minor_status = (OM_uint32) G_UNKNOWN_QOP; KRB5_LOG0(KRB5_ERR, "kg_seal() end, error G_UNKNOWN_QOP\n"); return (GSS_S_BAD_QOP); } /* validate the context handle */ if (! kg_validate_ctx_id(context_handle)) { *minor_status = (OM_uint32) G_VALIDATE_FAILED; KRB5_LOG0(KRB5_ERR, "kg_seal() kg_validate_ctx_id() end, " "error GSS_S_NO_CONTEXT\n"); return (GSS_S_NO_CONTEXT); } ctx = (krb5_gss_ctx_id_rec *) context_handle; if (ctx->subkey == NULL && !ctx->established) { *minor_status = KG_CTX_INCOMPLETE; return(GSS_S_NO_CONTEXT); } context = ctx->k5_context; if ((code = krb5_timeofday(context, &now))) { *minor_status = code; save_error_info(*minor_status, context); KRB5_LOG(KRB5_ERR, "kg_seal() end, krb5_timeofday() error code=%d\n", code); return (GSS_S_FAILURE); } switch (ctx->proto) { case 0: 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); break; case 1: code = gss_krb5int_make_seal_token_v3(context, ctx, input_message_buffer, output_message_buffer, conf_req_flag, toktype); break; default: code = G_UNKNOWN_QOP; /* XXX */ break; } if (code) { *minor_status = code; save_error_info(*minor_status, context); KRB5_LOG(KRB5_ERR, "kg_seal() end, make_seal_token_v1() " "error code=%d\n", code); return (GSS_S_FAILURE); } if (conf_state) *conf_state = conf_req_flag; *minor_status = 0; if (ctx->endtime < now) { (void) gss_release_buffer(minor_status, output_message_buffer); KRB5_LOG(KRB5_ERR, "kg_seal() end, error GSS_S_CONTEXT_EXPIRED " "ctx->endtime = %d\n", ctx->endtime); return (GSS_S_CONTEXT_EXPIRED); } KRB5_LOG0(KRB5_INFO, "kg_seal() end\n"); return (GSS_S_COMPLETE); } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * lib/gssapi/krb5/k5sealv3.c * * Copyright 2003,2004 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * */ /* draft-ietf-krb-wg-gssapi-cfx-05 */ #ifndef _KERNEL #include #include #define ASSERT assert #endif /* Solaris Kerberos */ #include "k5-int.h" /* for zap() */ #include "k5-platform.h" /* Solaris Kerberos */ #include "k5-platform-store_16.h" #include "k5-platform-store_64.h" #include "k5-platform-load_16.h" #include "k5-platform-load_64.h" #include "gssapiP_krb5.h" #include static int rotate_left (void *ptr, size_t bufsiz, size_t rc) { /* Optimize for receiving. After some debugging is done, the MIT implementation won't do any rotates on sending, and while debugging, they'll be randomly chosen. Return 1 for success, 0 for failure (ENOMEM). */ void *tbuf; if (bufsiz == 0) return 1; rc = rc % bufsiz; if (rc == 0) return 1; tbuf = MALLOC(rc); if (tbuf == 0) return 0; (void) memcpy(tbuf, ptr, rc); (void) memmove(ptr, (char *)ptr + rc, bufsiz - rc); (void) memcpy((char *)ptr + bufsiz - rc, tbuf, rc); FREE(tbuf, rc); return 1; } static const gss_buffer_desc empty_message = { 0, 0 }; #define FLAG_SENDER_IS_ACCEPTOR 0x01 #define FLAG_WRAP_CONFIDENTIAL 0x02 #define FLAG_ACCEPTOR_SUBKEY 0x04 krb5_error_code gss_krb5int_make_seal_token_v3 (krb5_context context, krb5_gss_ctx_id_rec *ctx, const gss_buffer_desc * message, gss_buffer_t token, int conf_req_flag, int toktype) { size_t bufsize = 16; unsigned char *outbuf = 0; krb5_error_code err; int key_usage; unsigned char acceptor_flag; const gss_buffer_desc *message2 = message; #ifdef CFX_EXERCISE size_t rrc; #endif size_t ec; unsigned short tok_id; krb5_checksum sum; krb5_keyblock *key; ASSERT(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0); ASSERT(ctx->big_endian == 0); acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; key_usage = (toktype == KG_TOK_WRAP_MSG ? (ctx->initiate ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL) : (ctx->initiate ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN)); if (ctx->have_acceptor_subkey) { key = ctx->acceptor_subkey; } else { key = ctx->enc; } #ifdef _KERNEL context->kef_cipher_mt = get_cipher_mech_type(context, key); context->kef_hash_mt = get_hash_mech_type(context, key); if ((err = init_key_kef(context->kef_cipher_mt, key))) { return (GSS_S_FAILURE); } #endif /* _KERNEL */ #ifdef CFX_EXERCISE { static int initialized = 0; if (!initialized) { srand(time(0)); initialized = 1; } } #endif if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { krb5_data plain; krb5_enc_data cipher; size_t ec_max; size_t tlen; /* 300: Adds some slop. */ if (SIZE_MAX - 300 < message->length) return ENOMEM; ec_max = SIZE_MAX - message->length - 300; if (ec_max > 0xffff) ec_max = 0xffff; /* * EC should really be a multiple (1) of the number of octets that * the cryptosystem would pad by if we didn't have the filler. * * For AES-CTS this will always be 0 and we expect no further * enctypes, so there should be no issue here. */ ec = 0; plain.length = message->length + 16 + ec; plain.data = MALLOC(plain.length); if (plain.data == NULL) return ENOMEM; /* Get size of ciphertext. */ if ((err = krb5_c_encrypt_length(context, ctx->enc->enctype, plain.length, &tlen))) { FREE(plain.data, plain.length); return (err); } bufsize = 16 + tlen; /* Allocate space for header plus encrypted data. */ outbuf = MALLOC(bufsize); if (outbuf == NULL) { FREE(plain.data, plain.length); return ENOMEM; } /* TOK_ID */ store_16_be(0x0504, outbuf); /* flags */ outbuf[2] = (acceptor_flag | (conf_req_flag ? FLAG_WRAP_CONFIDENTIAL : 0) | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); /* filler */ outbuf[3] = 0xff; /* EC */ store_16_be(ec, outbuf+4); /* RRC */ store_16_be(0, outbuf+6); store_64_be(ctx->seq_send, outbuf+8); (void) memcpy(plain.data, message->value, message->length); (void) memset(plain.data + message->length, 'x', ec); (void) memcpy(plain.data + message->length + ec, outbuf, 16); /* Should really use scatter/gather crypto interfaces */ cipher.ciphertext.data = (char *)outbuf + 16; cipher.ciphertext.length = bufsize - 16; cipher.enctype = key->enctype; err = krb5_c_encrypt(context, key, key_usage, 0, &plain, &cipher); (void) bzero(plain.data, plain.length); FREE(plain.data, plain.length); plain.data = 0; if (err) goto error; /* Now that we know we're returning a valid token.... */ ctx->seq_send++; #ifdef CFX_EXERCISE rrc = rand() & 0xffff; if (rotate_left(outbuf+16, bufsize-16, (bufsize-16) - (rrc % (bufsize - 16)))) store_16_be(rrc, outbuf+6); /* If the rotate fails, don't worry about it. */ #endif } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { krb5_data plain; /* Here, message is the application-supplied data; message2 is what goes into the output token. They may be the same, or message2 may be empty (for MIC). */ tok_id = 0x0504; wrap_with_checksum: plain.length = message->length + 16; plain.data = MALLOC(message->length + 16); if (plain.data == NULL) return ENOMEM; if (ctx->cksum_size > 0xffff) { FREE(plain.data, plain.length); return EINVAL; } bufsize = 16 + message2->length + ctx->cksum_size; outbuf = MALLOC(bufsize); if (outbuf == NULL) { FREE(plain.data, plain.length); plain.data = 0; err = ENOMEM; goto error; } /* TOK_ID */ store_16_be(tok_id, outbuf); /* flags */ outbuf[2] = (acceptor_flag | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); /* filler */ outbuf[3] = 0xff; if (toktype == KG_TOK_WRAP_MSG) { /* Use 0 for checksum calculation, substitute checksum length later. */ /* EC */ store_16_be(0, outbuf+4); /* RRC */ store_16_be(0, outbuf+6); } else { /* MIC and DEL store 0xFF in EC and RRC. */ store_16_be(0xffff, outbuf+4); store_16_be(0xffff, outbuf+6); } store_64_be(ctx->seq_send, outbuf+8); (void) memcpy(plain.data, message->value, message->length); (void) memcpy(plain.data + message->length, outbuf, 16); /* Fill in the output token -- data contents, if any, and space for the checksum. */ if (message2->length) (void) memcpy(outbuf + 16, message2->value, message2->length); sum.contents = outbuf + 16 + message2->length; sum.length = ctx->cksum_size; err = krb5_c_make_checksum(context, ctx->cksumtype, key, key_usage, &plain, &sum); bzero(plain.data, plain.length); FREE(plain.data, plain.length); plain.data = 0; if (err) { bzero(outbuf,bufsize); err = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto error; } if (sum.length != ctx->cksum_size) { err = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto error; } (void) memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size); krb5_free_checksum_contents(context, &sum); sum.contents = 0; /* Now that we know we're actually generating the token... */ ctx->seq_send++; if (toktype == KG_TOK_WRAP_MSG) { #ifdef CFX_EXERCISE rrc = rand() & 0xffff; /* If the rotate fails, don't worry about it. */ if (rotate_left(outbuf+16, bufsize-16, (bufsize-16) - (rrc % (bufsize - 16)))) store_16_be(rrc, outbuf+6); #endif /* Fix up EC field. */ store_16_be(ctx->cksum_size, outbuf+4); } else { store_16_be(0xffff, outbuf+6); } } else if (toktype == KG_TOK_MIC_MSG) { tok_id = 0x0404; message2 = &empty_message; goto wrap_with_checksum; } else if (toktype == KG_TOK_DEL_CTX) { /* * Solaris Kerberos: * No token should be generated for context deletion. Just * return. */ return 0; } else { err = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto error; } token->value = outbuf; token->length = bufsize; return 0; error: FREE(outbuf, bufsize); token->value = NULL; token->length = 0; return err; } /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX conf_state is only valid if SEAL. */ OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr, 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) { krb5_context context = *contextptr; krb5_data plain; gssint_uint64 seqnum; size_t ec, rrc; int key_usage; unsigned char acceptor_flag; krb5_checksum sum; krb5_error_code err; krb5_boolean valid; krb5_keyblock *key; ASSERT(toktype != KG_TOK_SEAL_MSG || ctx->enc != 0); ASSERT(ctx->big_endian == 0); ASSERT(ctx->proto == 1); if (qop_state) *qop_state = GSS_C_QOP_DEFAULT; acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0; key_usage = (toktype == KG_TOK_WRAP_MSG ? (!ctx->initiate ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL) : (!ctx->initiate ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN)); /* Oops. I wrote this code assuming ptr would be at the start of the token header. */ ptr -= 2; bodysize += 2; if (bodysize < 16) { defective: *minor_status = 0; return GSS_S_DEFECTIVE_TOKEN; } if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { *minor_status = (OM_uint32)G_BAD_DIRECTION; return GSS_S_BAD_SIG; } /* Two things to note here. First, we can't really enforce the use of the acceptor's subkey, if we're the acceptor; the initiator may have sent messages before getting the subkey. We could probably enforce it if we're the initiator. Second, if someone tweaks the code to not set the flag telling the krb5 library to generate a new subkey in the AP-REP message, the MIT library may include a subkey anyways -- namely, a copy of the AP-REQ subkey, if it was provided. So the initiator may think we wanted a subkey, and set the flag, even though we weren't trying to set the subkey. The "other" key, the one not asserted by the acceptor, will have the same value in that case, though, so we can just ignore the flag. */ if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) { key = ctx->acceptor_subkey; } else { key = ctx->enc; } #ifdef _KERNEL context->kef_cipher_mt = get_cipher_mech_type(context, key); context->kef_hash_mt = get_hash_mech_type(context, key); if ((err = init_key_kef(context->kef_cipher_mt, key))) { return (GSS_S_FAILURE); } #endif /* _KERNEL */ if (toktype == KG_TOK_WRAP_MSG) { if (load_16_be(ptr) != 0x0504) goto defective; if (ptr[3] != 0xff) goto defective; ec = load_16_be(ptr+4); rrc = load_16_be(ptr+6); seqnum = load_64_be(ptr+8); if (!rotate_left(ptr+16, bodysize-16, rrc)) { no_mem: *minor_status = ENOMEM; return GSS_S_FAILURE; } if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) { /* confidentiality */ krb5_enc_data cipher; unsigned char *althdr; size_t plainlen; if (conf_state) *conf_state = 1; /* Do we have no decrypt_size function? For all current cryptosystems, the ciphertext size will be larger than the plaintext size. */ cipher.enctype = key->enctype; cipher.ciphertext.length = bodysize - 16; cipher.ciphertext.data = (char *)ptr + 16; plain.length = plainlen = bodysize - 16; plain.data = MALLOC(plain.length); if (plain.data == NULL) goto no_mem; err = krb5_c_decrypt(context, key, key_usage, 0, &cipher, &plain); if (err) { goto error; } /* Don't use bodysize here! Use the fact that plain.length has been adjusted to the correct length. */ althdr = (uchar_t *)plain.data + plain.length - 16; if (load_16_be(althdr) != 0x0504 || althdr[2] != ptr[2] || althdr[3] != ptr[3] || memcmp(althdr+8, ptr+8, 8)) { FREE(plain.data, plainlen); goto defective; } message_buffer->length = plain.length - ec - 16; message_buffer->value = MALLOC(message_buffer->length); if (message_buffer->value == NULL) { FREE(plain.data, plainlen); goto no_mem; } (void) memcpy(message_buffer->value, plain.data, message_buffer->length); FREE(plain.data, plainlen); } else { /* no confidentiality */ if (conf_state) *conf_state = 0; if (ec + 16 < ec) /* overflow check */ goto defective; if (ec + 16 > bodysize) goto defective; /* We have: header | msg | cksum. We need cksum(msg | header). Rotate the first two. */ store_16_be(0, ptr+4); store_16_be(0, ptr+6); plain.length = bodysize-ec; plain.data = (char *)ptr; if (!rotate_left(ptr, bodysize-ec, 16)) goto no_mem; sum.length = ec; if (sum.length != ctx->cksum_size) { *minor_status = 0; return GSS_S_BAD_SIG; } sum.contents = ptr+bodysize-ec; sum.checksum_type = ctx->cksumtype; err = krb5_c_verify_checksum(context, key, key_usage, &plain, &sum, &valid); if (err) { *minor_status = err; return GSS_S_BAD_SIG; } if (!valid) { *minor_status = 0; return GSS_S_BAD_SIG; } message_buffer->length = plain.length - 16; message_buffer->value = MALLOC(message_buffer->length); if (message_buffer->value == NULL) goto no_mem; (void) memcpy(message_buffer->value, plain.data, message_buffer->length); /* * Solaris Kerberos: Restore the original token. * This allows the token to be detected as a duplicate if it * is passed in to gss_unwrap() again. */ if (!rotate_left(ptr, bodysize-ec, bodysize - ec - 16)) goto no_mem; store_16_be(ec, ptr+4); store_16_be(rrc, ptr+6); } err = g_order_check(&ctx->seqstate, seqnum); *minor_status = 0; return err; } else if (toktype == KG_TOK_MIC_MSG) { /* wrap token, no confidentiality */ if (load_16_be(ptr) != 0x0404) goto defective; verify_mic_1: if (ptr[3] != 0xff) goto defective; if (load_32_be(ptr+4) != (ulong_t)0xffffffffU) goto defective; seqnum = load_64_be(ptr+8); plain.length = message_buffer->length + 16; plain.data = MALLOC(plain.length); if (plain.data == NULL) goto no_mem; if (message_buffer->length) (void) memcpy(plain.data, message_buffer->value, message_buffer->length); (void) memcpy(plain.data + message_buffer->length, ptr, 16); sum.length = bodysize - 16; sum.contents = ptr + 16; sum.checksum_type = ctx->cksumtype; err = krb5_c_verify_checksum(context, key, key_usage, &plain, &sum, &valid); if (err) { error: FREE(plain.data, plain.length); *minor_status = err; save_error_info(*minor_status, context); return GSS_S_BAD_SIG; /* XXX */ } FREE(plain.data, plain.length); if (!valid) { *minor_status = 0; return GSS_S_BAD_SIG; } err = g_order_check(&ctx->seqstate, seqnum); *minor_status = 0; return err; } else if (toktype == KG_TOK_DEL_CTX) { if (load_16_be(ptr) != 0x0405) goto defective; message_buffer = (gss_buffer_t)&empty_message; goto verify_mic_1; } else { goto defective; } } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001 by the Massachusetts Institute of Technology. * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "gssapiP_krb5.h" #include "k5-int.h" /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX conf_state is only valid if SEAL. */ static 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; { krb5_error_code code; int conflen = 0; int signalg; int sealalg; gss_buffer_desc token; krb5_checksum cksum; krb5_checksum md5cksum; krb5_data plaind; char *data_ptr; krb5_timestamp now; unsigned char *plain; unsigned int cksum_len = 0; size_t plainlen; int direction; krb5_ui_4 seqnum; OM_uint32 retval; size_t sumlen, blocksize; int tmsglen; krb5_keyusage sign_usage = KG_USAGE_SIGN; KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() start\n"); /* Solaris Kerberos: make sure this is initialized */ *minor_status = 0; 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; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_DEFECTIVE_TOKEN\n"); return GSS_S_DEFECTIVE_TOKEN; } if ((toktype != KG_TOK_SEAL_MSG) && (sealalg != 0xffff)) { *minor_status = 0; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error2 GSS_S_DEFECTIVE_TOKEN\n"); 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; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error3 GSS_S_DEFECTIVE_TOKEN\n"); 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 == 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)|| (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 && signalg != SGN_ALG_HMAC_MD5)) { *minor_status = 0; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error4 GSS_S_DEFECTIVE_TOKEN\n"); return GSS_S_DEFECTIVE_TOKEN; } KRB5_LOG(KRB5_INFO, "kg_unseal_v1() signalg = %d\n", signalg); switch (signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_MD2_5: case SGN_ALG_HMAC_MD5: cksum_len = 8; if (toktype != KG_TOK_SEAL_MSG) sign_usage = 15; break; case SGN_ALG_3: cksum_len = 16; break; case SGN_ALG_HMAC_SHA1_DES3_KD: cksum_len = 20; break; default: *minor_status = 0; KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, error signalg=%d\n", signalg); return GSS_S_DEFECTIVE_TOKEN; } #ifdef _KERNEL /* * Because the ARCFOUR code bypasses the standard * crypto interfaces, we must make sure the kernel * crypto framework mechanism types are properly * initialized here. */ context->kef_cipher_mt = get_cipher_mech_type(context, ctx->seq); context->kef_hash_mt = get_hash_mech_type(context, ctx->seq); if ((code = init_key_kef(context->kef_cipher_mt, ctx->seq))) { *minor_status = code; return (GSS_S_FAILURE); } if ((code = init_key_kef(context->kef_cipher_mt, ctx->enc))) { *minor_status = code; return (GSS_S_FAILURE); } #endif /* _KERNEL */ /* get the token parameters */ if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, &seqnum))) { *minor_status = code; return(GSS_S_BAD_SIG); } /* decode the message, if SEAL */ if (toktype == KG_TOK_SEAL_MSG) { tmsglen = bodysize-(14+cksum_len); KRB5_LOG1(KRB5_INFO, "kg_unseal_v1() tmsglen = %d cksum_len = %d", tmsglen, cksum_len); KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == KG_TOK_SEAL_MSG\n"); if (sealalg != 0xffff) { if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { *minor_status = ENOMEM; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error ENOMEM\n"); return(GSS_S_FAILURE); } if (ctx->enc->enctype == ENCTYPE_ARCFOUR_HMAC) { unsigned char bigend_seqnum[4]; krb5_keyblock *enc_key; int i; bigend_seqnum[0] = (seqnum>>24) & 0xff; bigend_seqnum[1] = (seqnum>>16) & 0xff; bigend_seqnum[2] = (seqnum>>8) & 0xff; bigend_seqnum[3] = seqnum & 0xff; code = krb5_copy_keyblock (context, ctx->enc, &enc_key); if (code) { xfree_wrap(plain, tmsglen); *minor_status = code; return(GSS_S_FAILURE); } for (i = 0; i <= 15; i++) ((char *) enc_key->contents)[i] ^=0xf0; #ifndef _KERNEL /* * The enc_key contents were modified, delete the * key object so it doesn't get used later. */ if (enc_key->hKey != CK_INVALID_HANDLE) { (void)C_DestroyObject(krb_ctx_hSession(context), enc_key->hKey); enc_key->hKey = CK_INVALID_HANDLE; } #endif KRB5_LOG(KRB5_INFO, "kg_unseal_v1() enc_key->enctype = %d", enc_key->enctype); code = kg_arcfour_docrypt (context, enc_key, 0, &bigend_seqnum[0], 4, ptr+14+cksum_len, tmsglen, plain); krb5_free_keyblock (context, enc_key); } else { code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL, ptr+14+cksum_len, plain, tmsglen); } if (code) { xfree_wrap(plain, tmsglen); *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); /* * Solaris Kerberos: we want to perform a sanity check on the * pad length, so we know it can not be more than the blocksize. */ code = krb5_c_block_size(context, ctx->enc->enctype, &blocksize); if (code != 0) { if (sealalg != 0xffff) xfree_wrap(plain, tmsglen); *minor_status = code; return(GSS_S_FAILURE); } if (plain[tmsglen-1] > blocksize) { if (sealalg != 0xffff) xfree_wrap(plain, tmsglen); *minor_status = KG_BAD_LENGTH; return(GSS_S_FAILURE); } token.length = tmsglen - conflen - plain[tmsglen-1]; } if (token.length) { if ((token.value = (void *) xmalloc(token.length)) == NULL) { if (sealalg != 0xffff) xfree_wrap(plain, tmsglen); *minor_status = ENOMEM; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error2 ENOMEM\n"); return(GSS_S_FAILURE); } (void) memcpy(token.value, plain+conflen, token.length); } else { token.value = NULL; } } else if (toktype == KG_TOK_SIGN_MSG) { KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == KG_TOK_SIGN_MSG\n"); token = *message_buffer; plain = token.value; plainlen = token.length; } else { KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == NULL\n"); token.length = 0; token.value = NULL; plain = token.value; plainlen = token.length; } /* 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_DES_MAC: case SGN_ALG_3: md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; break; case SGN_ALG_HMAC_MD5: md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; break; case SGN_ALG_HMAC_SHA1_DES3_KD: md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; break; default: KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, error2 signalg=%d\n", signalg); #ifndef _KERNEL abort (); #else *minor_status = 0; return(GSS_S_DEFECTIVE_TOKEN); #endif /* _KERNEL */ } code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); if (code) { KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_checksum_length() error " "code=%d\n", code); return(code); } md5cksum.length = (size_t)sumlen; switch (signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_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_wrap(plain, tmsglen); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = ENOMEM; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error3 ENOMEM\n"); 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, ctx->seq, sign_usage, &plaind, &md5cksum); xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen)); if (code) { if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = code; KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_make_checksum() " "error code = %d\n", code); return(GSS_S_FAILURE); } 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_wrap(md5cksum.contents, md5cksum.length); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = code; KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, kg_encrypt() error" "code = %d\n", 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); break; case SGN_ALG_MD2_5: if (!ctx->seed_init && (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { xfree_wrap(md5cksum.contents, md5cksum.length); if (sealalg != 0xffff) xfree_wrap(plain, tmsglen); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = code; return GSS_S_FAILURE; } if (! (data_ptr = (void *) xmalloc(sizeof(ctx->seed) + 8 + (ctx->big_endian ? token.length : plainlen)))) { xfree_wrap(md5cksum.contents, md5cksum.length); if (sealalg == 0) xfree_wrap(plain, tmsglen); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *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_wrap(md5cksum.contents, md5cksum.length); code = krb5_c_make_checksum(context, md5cksum.checksum_type, ctx->seq, KG_USAGE_SIGN, &plaind, &md5cksum); xfree_wrap(data_ptr, 8 + sizeof(ctx->seed) + (ctx->big_endian ? token.length : plainlen)); if (code) { if (sealalg == 0) xfree_wrap(plain, tmsglen); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = code; return(GSS_S_FAILURE); } code = memcmp(md5cksum.contents, ptr+14, 8); /* Falls through to defective-token?? */ /* FALLTHROUGH */ default: *minor_status = 0; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error SGN_ALG_MD2_5 " "GSS_S_DEFECTIVE_TOKEN\n"); return(GSS_S_DEFECTIVE_TOKEN); case SGN_ALG_HMAC_SHA1_DES3_KD: case SGN_ALG_HMAC_MD5: /* 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_wrap(plain, tmsglen); if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = ENOMEM; return(GSS_S_FAILURE); } (void) memcpy(data_ptr, ptr-2, 8); if (ctx->big_endian) { KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 1\n"); (void) memcpy(data_ptr+8, token.value, token.length); } else { KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 0\n"); (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, ctx->seq, sign_usage, &plaind, &md5cksum); xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen)); if (code) { if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = code; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error " "SGN_ALG_HMAC_SHA1_DES3_KD GSS_S_FAILURE\n"); return(GSS_S_FAILURE); } /* compare the computed checksum against the transmitted checksum */ code = memcmp(md5cksum.contents, ptr+14, cksum_len); KRB5_LOG(KRB5_INFO, "kg_unseal_v1() memcmp %d bytes", cksum_len); break; } xfree_wrap(md5cksum.contents, md5cksum.length); if (sealalg != 0xffff) xfree_wrap(plain, tmsglen); if (code) { if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = 0; KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG\n"); return(GSS_S_BAD_SIG); } 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; KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_timeofday()" "error code = %d\n", code); return(GSS_S_FAILURE); } if (now > ctx->endtime) { *minor_status = 0; KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error " "now %d > ctx->endtime %d\n", now, ctx->endtime); return(GSS_S_CONTEXT_EXPIRED); } /* do sequencing checks */ if ((ctx->initiate && direction != 0xff) || (!ctx->initiate && direction != 0)) { if (toktype == KG_TOK_SEAL_MSG) { xfree_wrap(token.value, token.length); /* Solaris Kerberos: just to be safe since token.value is an * output parameter. */ token.value = NULL; token.length = 0; } *minor_status = (OM_uint32) G_BAD_DIRECTION; KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG " "G_BAD_DIRECTION ctx->initiate = %d " "direction = %d\n", ctx->initiate, direction); return(GSS_S_BAD_SIG); } retval = g_order_check(&(ctx->seqstate), (gssint_uint64)seqnum); /* It got through unscathed, adjust the output message buffer. */ if (retval == 0 && toktype == KG_TOK_SEAL_MSG) *message_buffer = token; *minor_status = 0; KRB5_LOG(KRB5_INFO, "kg_unseal_v1() end, retval = %d\n", retval); 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(minor_status, context_handle, input_token_buffer, message_buffer, conf_state, qop_state, toktype) 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; int toktype2; KRB5_LOG0(KRB5_INFO, "kg_unseal() start \n"); /* validate the context handle */ if (! kg_validate_ctx_id(context_handle)) { *minor_status = (OM_uint32) G_VALIDATE_FAILED; KRB5_LOG0(KRB5_ERR, "kg_unseal() end, kg_validate_ctx_id() error " "G_VALIDATE_FAILED \n"); return(GSS_S_NO_CONTEXT); } ctx = (krb5_gss_ctx_id_rec *) context_handle; if (! ctx->established) { *minor_status = KG_CTX_INCOMPLETE; KRB5_LOG0(KRB5_ERR, "kg_unseal() end, error ! ctx->established \n"); 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->proto) switch (toktype) { case KG_TOK_SIGN_MSG: toktype2 = 0x0404; break; case KG_TOK_SEAL_MSG: toktype2 = 0x0504; break; case KG_TOK_DEL_CTX: toktype2 = 0x0405; break; default: toktype2 = toktype; break; } else toktype2 = toktype; err = g_verify_token_header(ctx->mech_used, (uint32_t *)&bodysize, &ptr, toktype2, input_token_buffer->length, !ctx->proto); if (err) { *minor_status = err; return GSS_S_DEFECTIVE_TOKEN; } if (ctx->proto == 0) { err = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, message_buffer, conf_state, qop_state, toktype); } else { err = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx, ptr, bodysize, message_buffer, conf_state, qop_state, toktype); } *minor_status = err; #ifndef _KERNEL if (err != 0) save_error_info (*minor_status, ctx->k5_context); #endif KRB5_LOG(KRB5_INFO, "kg_unseal() end, err = %d", err); return(err); } /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" /* * $Id: seal.c 16171 2004-03-15 17:45:01Z raeburn $ */ /*ARGSUSED*/ OM_uint32 krb5_gss_seal(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer #ifdef _KERNEL , gssd_ctx_verifier #endif ) 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; #ifdef _KERNEL OM_uint32 gssd_ctx_verifier; #endif { #ifdef KRB5_NO_PRIVACY /* * conf_req_flag must be zero; * encryption is disallowed * for global version */ if (conf_req_flag) return (GSS_S_FAILURE); #endif return(kg_seal(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, KG_TOK_SEAL_MSG)); } /* V2 interface */ OM_uint32 krb5_gss_wrap(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer) OM_uint32 *minor_status; gss_ctx_id_t context_handle; int conf_req_flag; gss_qop_t qop_req; gss_buffer_t input_message_buffer; int *conf_state; gss_buffer_t output_message_buffer; { #ifdef KRB5_NO_PRIVACY return (GSS_S_FAILURE); #else return(kg_seal(minor_status, context_handle, conf_req_flag, (int) qop_req, input_message_buffer, conf_state, output_message_buffer, KG_TOK_WRAP_MSG)); #endif } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * lib/gssapi/krb5/ser_sctx.c * * Copyright 1995, 2004 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * */ /* * ser_sctx.c - Handle [de]serialization of GSSAPI security context. */ /* Solaris Kerberos: order is important here. include gssapiP_krb5.h * before all others, otherwise we get a LINT error from MALLOC macro * being redefined in mechglueP.h */ #include "gssapiP_krb5.h" #include "k5-int.h" /* * This module contains routines to [de]serialize * krb5_gss_enc_desc and krb5_gss_ctx_id_t. * XXX This whole serialization abstraction is unnecessary in a * non-messaging environment, which krb5 is. Someday, this should * all get redone without the extra level of indirection. I've done * some of this work here, since adding new serializers is an internal * krb5 interface, and I won't use those. There is some more * deobfuscation (no longer anonymizing pointers, mostly) which could * still be done. --marc */ /*ARGSUSED*/ static krb5_error_code kg_oid_externalize(kcontext, arg, buffer, lenremain) krb5_context kcontext; krb5_pointer arg; krb5_octet **buffer; size_t *lenremain; { gss_OID oid = (gss_OID) arg; krb5_error_code err; err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); if (err) return err; err = krb5_ser_pack_int32((krb5_int32) oid->length, buffer, lenremain); if (err) return err; err = krb5_ser_pack_bytes((krb5_octet *) oid->elements, oid->length, buffer, lenremain); if (err) return err; err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); return err; } /*ARGSUSED*/ static krb5_error_code kg_oid_internalize(kcontext, argp, buffer, lenremain) krb5_context kcontext; krb5_pointer *argp; krb5_octet **buffer; size_t *lenremain; { gss_OID oid; krb5_int32 ibuf; krb5_octet *bp; size_t remain; bp = *buffer; remain = *lenremain; /* Read in and check our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) return (EINVAL); if (ibuf != KV5M_GSS_OID) return (EINVAL); oid = (gss_OID) MALLOC(sizeof(gss_OID_desc)); if (oid == NULL) return ENOMEM; if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { FREE(oid, sizeof(gss_OID_desc)); return EINVAL; } oid->length = ibuf; oid->elements = MALLOC(ibuf); if (oid->elements == 0) { FREE(oid, sizeof(gss_OID_desc)); return ENOMEM; } if (krb5_ser_unpack_bytes((krb5_octet *) oid->elements, oid->length, &bp, &remain)) { FREE(oid->elements, oid->length); FREE(oid, sizeof(gss_OID_desc)); return EINVAL; } /* Read in and check our trailing magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { FREE(oid->elements, oid->length); FREE(oid, sizeof(gss_OID_desc)); return (EINVAL); } if (ibuf != KV5M_GSS_OID) { FREE(oid->elements, oid->length); FREE(oid, sizeof(gss_OID_desc)); return (EINVAL); } *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) oid; return 0; } /*ARGSUSED*/ static krb5_error_code kg_oid_size(kcontext, arg, sizep) krb5_context kcontext; krb5_pointer arg; size_t *sizep; { krb5_error_code kret; gss_OID oid; size_t required; kret = EINVAL; /*LINTED*/ if ((oid = (gss_OID) arg)) { required = 2*sizeof(krb5_int32); /* For the header and trailer */ required += sizeof(krb5_int32); required += oid->length; kret = 0; *sizep += required; } return(kret); } /*ARGSUSED*/ static krb5_error_code kg_queue_externalize(kcontext, arg, buffer, lenremain) krb5_context kcontext; krb5_pointer arg; krb5_octet **buffer; size_t *lenremain; { krb5_error_code err; err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); if (err == 0) err = g_queue_externalize(arg, buffer, lenremain); if (err == 0) err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); return err; } /*ARGSUSED*/ static krb5_error_code kg_queue_internalize(kcontext, argp, buffer, lenremain) krb5_context kcontext; krb5_pointer *argp; krb5_octet **buffer; size_t *lenremain; { krb5_int32 ibuf; krb5_octet *bp; size_t remain; krb5_error_code err; bp = *buffer; remain = *lenremain; /* Read in and check our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) return (EINVAL); if (ibuf != KV5M_GSS_QUEUE) return (EINVAL); err = g_queue_internalize(argp, &bp, &remain); if (err) return err; /* Read in and check our trailing magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { g_order_free(argp); return (EINVAL); } if (ibuf != KV5M_GSS_QUEUE) { g_order_free(argp); return (EINVAL); } *buffer = bp; *lenremain = remain; return 0; } /*ARGSUSED*/ static krb5_error_code kg_queue_size(kcontext, arg, sizep) krb5_context kcontext; krb5_pointer arg; size_t *sizep; { krb5_error_code kret; size_t required; kret = EINVAL; if (arg) { required = 2*sizeof(krb5_int32); /* For the header and trailer */ (void) g_queue_size(arg, &required); kret = 0; *sizep += required; } return(kret); } /* * Determine the size required for this krb5_gss_ctx_id_rec. */ krb5_error_code kg_ctx_size(kcontext, arg, sizep) krb5_context kcontext; krb5_pointer arg; size_t *sizep; { krb5_error_code kret; krb5_gss_ctx_id_rec *ctx; size_t required; /* * krb5_gss_ctx_id_rec requires: * krb5_int32 for KG_CONTEXT * krb5_int32 for initiate. * krb5_int32 for established. * krb5_int32 for big_endian. * krb5_int32 for have_acceptor_subkey. * krb5_int32 for seed_init. * krb5_int32 for gss_flags. * sizeof(seed) for seed * ... for here * ... for there * ... for subkey * krb5_int32 for signalg. * krb5_int32 for cksum_size. * krb5_int32 for sealalg. * ... for enc * ... for seq * krb5_int32 for endtime. * krb5_int32 for flags. * krb5_int64 for seq_send. * krb5_int64 for seq_recv. * ... for seqstate * ... for auth_context * ... for mech_used * krb5_int32 for proto * krb5_int32 for cksumtype * ... for acceptor_subkey * krb5_int32 for acceptor_key_cksumtype * krb5_int32 for cred_rcache * krb5_int32 for trailer. */ kret = EINVAL; /*LINTED*/ if ((ctx = (krb5_gss_ctx_id_rec *) arg)) { required = 17*sizeof(krb5_int32); required += 2*sizeof(krb5_int64); required += sizeof(ctx->seed); kret = 0; if (!kret && ctx->here) kret = krb5_size_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) ctx->here, &required); if (!kret && ctx->there) kret = krb5_size_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) ctx->there, &required); if (!kret && ctx->subkey) kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->subkey, &required); if (!kret && ctx->enc) kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->enc, &required); if (!kret && ctx->seq) kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->seq, &required); if (!kret) kret = kg_oid_size(kcontext, (krb5_pointer) ctx->mech_used, &required); if (!kret && ctx->seqstate) kret = kg_queue_size(kcontext, ctx->seqstate, &required); #ifndef PROVIDE_KERNEL_IMPORT if (!kret) kret = krb5_size_opaque(kcontext, KV5M_CONTEXT, (krb5_pointer) ctx->k5_context, &required); if (!kret) kret = krb5_size_opaque(kcontext, KV5M_AUTH_CONTEXT, (krb5_pointer) ctx->auth_context, &required); #endif if (!kret && ctx->acceptor_subkey) kret = krb5_size_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->acceptor_subkey, &required); if (!kret) *sizep += required; } return(kret); } /* * Externalize this krb5_gss_ctx_id_ret. */ krb5_error_code kg_ctx_externalize(kcontext, arg, buffer, lenremain) krb5_context kcontext; krb5_pointer arg; krb5_octet **buffer; size_t *lenremain; { krb5_error_code kret; krb5_gss_ctx_id_rec *ctx; size_t required; krb5_octet *bp; size_t remain; #ifndef _KERNEL krb5int_access kaccess; kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); if (kret) return(kret); #endif required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; /*LINTED*/ if ((ctx = (krb5_gss_ctx_id_rec *) arg)) { kret = ENOMEM; if (!kg_ctx_size(kcontext, arg, &required) && (required <= remain)) { /* Our identifier */ (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); /* Now static data */ (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->established, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags, &bp, &remain); (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed, sizeof(ctx->seed), &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->endtime, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags, &bp, &remain); #ifndef _KERNEL (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_send, &bp, &remain); (void) (*kaccess.krb5_ser_pack_int64)((krb5_int64) ctx->seq_recv, &bp, &remain); #else (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_send, &bp, &remain); (void) krb5_ser_pack_int64((krb5_int64) ctx->seq_recv, &bp, &remain); #endif /* Now dynamic data */ kret = 0; if (!kret && ctx->mech_used) kret = kg_oid_externalize(kcontext, ctx->mech_used, &bp, &remain); if (!kret && ctx->here) kret = krb5_externalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) ctx->here, &bp, &remain); if (!kret && ctx->there) kret = krb5_externalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer) ctx->there, &bp, &remain); if (!kret && ctx->subkey) kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->subkey, &bp, &remain); if (!kret && ctx->enc) kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->enc, &bp, &remain); if (!kret && ctx->seq) kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->seq, &bp, &remain); if (!kret && ctx->seqstate) kret = kg_queue_externalize(kcontext, ctx->seqstate, &bp, &remain); #ifndef PROVIDE_KERNEL_IMPORT if (!kret) kret = krb5_externalize_opaque(kcontext, KV5M_CONTEXT, (krb5_pointer) ctx->k5_context, &bp, &remain); if (!kret) kret = krb5_externalize_opaque(kcontext, KV5M_AUTH_CONTEXT, (krb5_pointer) ctx->auth_context, &bp, &remain); #endif if (!kret) kret = krb5_ser_pack_int32((krb5_int32) ctx->proto, &bp, &remain); if (!kret) kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype, &bp, &remain); if (!kret && ctx->acceptor_subkey) kret = krb5_externalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer) ctx->acceptor_subkey, &bp, &remain); if (!kret) kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype, &bp, &remain); if (!kret) kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache, &bp, &remain); /* trailer */ if (!kret) kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); if (!kret) { *buffer = bp; *lenremain = remain; } } } return(kret); } /* * Internalize this krb5_gss_ctx_id_t. */ krb5_error_code kg_ctx_internalize(kcontext, argp, buffer, lenremain) krb5_context kcontext; krb5_pointer *argp; krb5_octet **buffer; size_t *lenremain; { krb5_error_code kret; krb5_gss_ctx_id_rec *ctx; krb5_int32 ibuf; krb5_octet *bp; size_t remain; #ifndef _KERNEL krb5int_access kaccess; kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); if (kret) return(kret); #endif bp = *buffer; remain = *lenremain; kret = EINVAL; /* Read our magic number */ if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) ibuf = 0; if (ibuf == KG_CONTEXT) { kret = ENOMEM; /* Get a context */ if ((remain >= (17*sizeof(krb5_int32) + 2*sizeof(krb5_int64) + sizeof(ctx->seed))) && (ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))) { (void) memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); ctx->k5_context = kcontext; /* Get static data */ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->initiate = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->established = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->big_endian = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->have_acceptor_subkey = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->seed_init = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->gss_flags = (int) ibuf; (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed, sizeof(ctx->seed), &bp, &remain); (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->signalg = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->cksum_size = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->sealalg = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->endtime = (krb5_timestamp) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->krb_flags = (krb5_flags) ibuf; #ifndef _KERNEL (void) (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_send, &bp, &remain); kret = (*kaccess.krb5_ser_unpack_int64)((krb5_int64 *)&ctx->seq_recv, &bp, &remain); #else (void) krb5_ser_unpack_int64((krb5_int64 *) (&ctx->seq_send), &bp, &remain); kret = krb5_ser_unpack_int64((krb5_int64 *) (&ctx->seq_recv), &bp, &remain); #endif if (kret) { xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec)); return kret; } if ((kret = kg_oid_internalize(kcontext, (krb5_pointer *) &ctx->mech_used, &bp, &remain))) { if (kret == EINVAL) kret = 0; } /* Now get substructure data */ if ((kret = krb5_internalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer *) &ctx->here, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret && (kret = krb5_internalize_opaque(kcontext, KV5M_PRINCIPAL, (krb5_pointer *) &ctx->there, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret && (kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &ctx->subkey, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret && (kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &ctx->enc, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret && (kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &ctx->seq, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret) { kret = kg_queue_internalize(kcontext, &ctx->seqstate, &bp, &remain); if (kret == EINVAL) kret = 0; } #ifndef PROVIDE_KERNEL_IMPORT if (!kret) kret = krb5_internalize_opaque(kcontext, KV5M_CONTEXT, (krb5_pointer *) &ctx->k5_context, &bp, &remain); if (!kret) kret = krb5_internalize_opaque(kcontext, KV5M_AUTH_CONTEXT, (krb5_pointer *) &ctx->auth_context, &bp, &remain); #endif if (!kret) kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->proto = ibuf; if (!kret) kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->cksumtype = ibuf; if (!kret && (kret = krb5_internalize_opaque(kcontext, KV5M_KEYBLOCK, (krb5_pointer *) &ctx->acceptor_subkey, &bp, &remain))) { if (kret == EINVAL) kret = 0; } if (!kret) kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->cred_rcache = ibuf; if (!kret) kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->acceptor_subkey_cksumtype = ibuf; /* Get trailer */ if (!kret) kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); if (!kret && ibuf != KG_CONTEXT) kret = EINVAL; if (!kret) { *buffer = bp; *lenremain = remain; *argp = (krb5_pointer) ctx; } else { if (ctx->seq) krb5_free_keyblock(kcontext, ctx->seq); if (ctx->enc) krb5_free_keyblock(kcontext, ctx->enc); if (ctx->subkey) krb5_free_keyblock(kcontext, ctx->subkey); if (ctx->there) krb5_free_principal(kcontext, ctx->there); if (ctx->here) krb5_free_principal(kcontext, ctx->here); xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec)); } } } return(kret); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" /* * $Id: sign.c 16171 2004-03-15 17:45:01Z raeburn $ */ /*ARGSUSED*/ OM_uint32 krb5_gss_sign(minor_status, context_handle, qop_req, message_buffer, message_token #ifdef _KERNEL , gssd_ctx_verifier #endif ) OM_uint32 *minor_status; gss_ctx_id_t context_handle; int qop_req; gss_buffer_t message_buffer; gss_buffer_t message_token; #ifdef _KERNEL OM_uint32 gssd_ctx_verifier; #endif { return(kg_seal(minor_status, context_handle, 0, qop_req, message_buffer, NULL, message_token, KG_TOK_SIGN_MSG)); } /* V2 interface */ OM_uint32 krb5_gss_get_mic(minor_status, context_handle, qop_req, message_buffer, message_token) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_qop_t qop_req; gss_buffer_t message_buffer; gss_buffer_t message_token; { return(kg_seal(minor_status, context_handle, 0, (int) qop_req, message_buffer, NULL, message_token, KG_TOK_MIC_MSG)); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" /* * $Id: unseal.c 16171 2004-03-15 17:45:01Z raeburn $ */ /*ARGSUSED*/ OM_uint32 krb5_gss_unseal(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state #ifdef _KERNEL , gssd_ctx_verifier #endif ) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t input_message_buffer; gss_buffer_t output_message_buffer; int *conf_state; int *qop_state; #ifdef _KERNEL OM_uint32 gssd_ctx_verifier; #endif { return(kg_unseal(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state, KG_TOK_SEAL_MSG)); } /* V2 interface */ OM_uint32 krb5_gss_unwrap(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t input_message_buffer; gss_buffer_t output_message_buffer; int *conf_state; gss_qop_t *qop_state; { #ifdef KRB5_NO_PRIVACY return (GSS_S_FAILURE); #else OM_uint32 rstat; int qstate; rstat = kg_unseal(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, &qstate, KG_TOK_WRAP_MSG); if (!rstat && qop_state) *qop_state = (gss_qop_t) qstate; return(rstat); #endif } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright2001 by the Massachusetts Institute of Technology. * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Solaris Kerberos: order is important here. include gssapiP_krb5.h * before all others, otherwise we get a LINT error from MALLOC macro * being redefined in mechglueP.h */ #include #include /* Solaris Kerberos defines memory management macros in */ /* #include */ /* * $Id: util_crypt.c,v 1.11.6.3 2000/06/03 06:09:45 tlyu Exp $ */ int kg_confounder_size(context, key) krb5_context context; krb5_keyblock *key; { krb5_error_code code; size_t blocksize; /* We special case rc4*/ if (key->enctype == ENCTYPE_ARCFOUR_HMAC) return 8; code = krb5_c_block_size(context, key->enctype, &blocksize); if (code) return(-1); /* XXX */ return(blocksize); } krb5_error_code kg_make_confounder(context, key, buf) krb5_context context; krb5_keyblock *key; unsigned char *buf; { krb5_error_code code; size_t blocksize; krb5_data lrandom; code = krb5_c_block_size(context, key->enctype, &blocksize); if (code) return(code); lrandom.length = blocksize; lrandom.data = (char *) buf; return(krb5_c_random_make_octets(context, &lrandom)); } int kg_encrypt_size(context, key, n) krb5_context context; krb5_keyblock *key; int n; { size_t enclen; if (krb5_c_encrypt_length(context, key->enctype, n, &enclen) != 0) return(-1); /* XXX */ return(enclen); } krb5_error_code kg_encrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; int usage; krb5_pointer iv; krb5_const_pointer in; krb5_pointer out; unsigned int length; { krb5_error_code code; size_t blocksize; krb5_data ivd, *pivd, inputd; krb5_enc_data outputd; KRB5_LOG0(KRB5_INFO, "kg_encrypt() start."); if (iv) { code = krb5_c_block_size(context, key->enctype, &blocksize); if (code) return(code); ivd.length = blocksize; ivd.data = MALLOC(ivd.length); if (ivd.data == NULL) return ENOMEM; (void) memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; } inputd.length = length; inputd.data = (char *)in; /* Solaris Kerberos */ outputd.ciphertext.length = length; outputd.ciphertext.data = out; code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd); if (pivd != NULL) krb5_free_data_contents(context, pivd); KRB5_LOG(KRB5_INFO, "kg_encrypt() end. code = %d", code); return code; } /* length is the length of the cleartext. */ krb5_error_code kg_decrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; int usage; krb5_pointer iv; krb5_const_pointer in; krb5_pointer out; unsigned int length; { krb5_error_code code; size_t blocksize; krb5_data ivd, *pivd, outputd; krb5_enc_data inputd; KRB5_LOG0(KRB5_INFO, "kg_decrypt() start."); if (iv) { code = krb5_c_block_size(context, key->enctype, &blocksize); if (code) return(code); ivd.length = blocksize; ivd.data = MALLOC(ivd.length); if (ivd.data == NULL) return ENOMEM; (void) memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; } inputd.enctype = ENCTYPE_UNKNOWN; inputd.ciphertext.length = length; inputd.ciphertext.data = (char *)in; /* Solaris Kerberos */ outputd.length = length; outputd.data = out; code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd); if (pivd != NULL) krb5_free_data_contents(context, pivd); KRB5_LOG(KRB5_INFO, "kg_decrypt() end. code = %d", code); return code; } krb5_error_code kg_arcfour_docrypt (krb5_context context, const krb5_keyblock *longterm_key , int ms_usage, const unsigned char *kd_data, size_t kd_data_len, const unsigned char *input_buf, size_t input_len, unsigned char *output_buf) { krb5_error_code code; krb5_data input, output; krb5_keyblock seq_enc_key, usage_key; unsigned char t[4]; KRB5_LOG0(KRB5_INFO, "kg_arcfour_docrypt() start"); bzero(&usage_key, sizeof(krb5_keyblock)); bzero(&seq_enc_key, sizeof(krb5_keyblock)); usage_key.length = longterm_key->length; usage_key.contents = MALLOC(usage_key.length); usage_key.enctype = longterm_key->enctype; usage_key.dk_list = NULL; #ifdef _KERNEL usage_key.kef_mt = longterm_key->kef_mt; code = init_key_kef(longterm_key->kef_mt, &usage_key); if (code) return (code); #endif /* _KERNEL */ if (usage_key.contents == NULL) return (ENOMEM); seq_enc_key.length = longterm_key->length; seq_enc_key.contents = MALLOC(seq_enc_key.length); seq_enc_key.enctype = longterm_key->enctype; seq_enc_key.dk_list = NULL; #ifdef _KERNEL seq_enc_key.kef_mt = longterm_key->kef_mt; code = init_key_kef(longterm_key->kef_mt, &seq_enc_key); if (code) return (code); #endif /* _KERNEL */ if (seq_enc_key.contents == NULL) { FREE ((void *) usage_key.contents, usage_key.length); return (ENOMEM); } t[0] = ms_usage &0xff; t[1] = (ms_usage>>8) & 0xff; t[2] = (ms_usage>>16) & 0xff; t[3] = (ms_usage>>24) & 0xff; input.data = (void *) &t; input.length = 4; output.data = (void *) usage_key.contents; output.length = usage_key.length; #ifdef _KERNEL code = krb5_hmac(context, longterm_key, &input, &output); #else code = krb5_hmac(context, &krb5int_hash_md5, longterm_key, 1, &input, &output); #endif /* _KERNEL */ if (code) goto cleanup_arcfour; input.data = ( void *) kd_data; input.length = kd_data_len; output.data = (void *) seq_enc_key.contents; #ifdef _KERNEL code = krb5_hmac(context, &usage_key, &input, &output); #else code = krb5_hmac(context, &krb5int_hash_md5, &usage_key, 1, &input, &output); #endif /* _KERNEL */ if (code) goto cleanup_arcfour; input.data = ( void * ) input_buf; input.length = input_len; output.data = (void * ) output_buf; output.length = input_len; /* * Call the arcfour encryption method directly here, we cannot * use the standard "krb5_c_encrypt" interface because we just * want the arcfour algorithm applied and not the additional MD5-HMAC * which are applied when using the standard interface. */ code = krb5int_enc_arcfour.encrypt(context, &seq_enc_key, 0, &input, &output); cleanup_arcfour: bzero ((void *) seq_enc_key.contents, seq_enc_key.length); bzero ((void *) usage_key.contents, usage_key.length); FREE ((void *) usage_key.contents, usage_key.length); FREE ((void *) seq_enc_key.contents, seq_enc_key.length); KRB5_LOG(KRB5_INFO, "kg_arcfour_docrypt() end code = %d", code); return (code); } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * $Id: util_ordering.c 19310 2007-03-29 21:36:38Z tlyu $ */ /* * SUNW15resync * Left this alone (MIT version causes STC gss_verify_mic(6) test failure) * as it has bug fixes that MIT does not yet. */ /* * functions to check sequence numbers for replay and sequencing */ #include "mechglueP.h" #include "gssapiP_generic.h" #define QUEUE_LENGTH 20 typedef struct _queue { int do_replay; int do_sequence; int start; int length; gssint_uint64 firstnum; gssint_uint64 elem[QUEUE_LENGTH]; gssint_uint64 mask; } queue; /* rep invariant: * - the queue is a circular queue. The first element (q->elem[q->start]) * is the oldest. The last element is the newest. */ #define QSIZE(q) (sizeof((q)->elem)/sizeof((q)->elem[0])) #define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)]) /* * mask(max) is 2 ** 64 - 1, and half is 2 ** 63. * |-------------------------------|-----------------------------| * 0 half mask * |-------------------------------| * half range ( 2 ** 63 ) * * Here, the distance between n1 and n2 is used, if it falls * in the "half range", normal integer comparison is enough. * * If the distance is bigger than half of the range, one of them must * have passed the 'mask' point while the other one didn't. In this * case, the result should be the reverse of normal comparison, i.e. * the smaller one is considered bigger. * * If we shift the smaller value by adding 'mask' to it, * the distance will be in half range again. * * The assumption is that the out of order event will not * happen too often. If the distance is really bigger than half range, * (1 is expected, but half + 2 arrives) we really don't know if it's a * GAP token or an OLD token that wrapped. */ static int after(gssint_uint64 n1, gssint_uint64 n2, gssint_uint64 mask) { int bigger; gssint_uint64 diff; gssint_uint64 half; /* * rule 1: same number. * This may be ambiguous, but the caller of this function, * g_order_check already takes care of it. */ if (n1 == n2) return (0); half = 1 + (mask >> 1); if (n1 > n2) { diff = n1 - n2; bigger = 1; } else { diff = n2 - n1; bigger = 0; } /* rule 2: in the same half range, normal comparison is enough */ if (diff < half) return bigger; n1 &= half; /* rule 3: different half, and n1 is on upper, n2 is bigger */ /* rule 4: different half, and n1 is on lower, n1 is bigger */ if (n1 != 0) return (0); return (1); } static void queue_insert(queue *q, int after, gssint_uint64 seqnum) { /* insert. this is not the fastest way, but it's easy, and it's optimized for insert at end, which is the common case */ int i; /* common case: at end, after == q->start+q->length-1 */ /* move all the elements (after,last] up one slot */ for (i=q->start+q->length-1; i>after; i--) QELEM(q,i+1) = QELEM(q,i); /* fill in slot after+1 */ QELEM(q,after+1) = seqnum; /* Either increase the length by one, or move the starting point up one (deleting the first element, which got bashed above), as appropriate. */ if (q->length == QSIZE(q)) { q->start++; if (q->start == QSIZE(q)) q->start = 0; } else { q->length++; } } gss_int32 g_order_init(void **vqueue, gssint_uint64 seqnum, int do_replay, int do_sequence, int wide_nums) { queue *q; if ((q = (queue *) MALLOC(sizeof(queue))) == NULL) return(ENOMEM); q->do_replay = do_replay; q->do_sequence = do_sequence; q->mask = wide_nums ? ~(gssint_uint64)0 : 0xffffffffUL; q->start = 0; q->length = 1; q->firstnum = seqnum; q->elem[q->start] = ((gssint_uint64)0 - 1) & q->mask; *vqueue = (void *) q; return(0); } gss_int32 g_order_check(void **vqueue, gssint_uint64 seqnum) { queue *q; int i; gssint_uint64 expected; q = (queue *) (*vqueue); if (!q->do_replay && !q->do_sequence) return(GSS_S_COMPLETE); /* All checks are done relative to the initial sequence number, to avoid (or at least put off) the pain of wrapping. */ seqnum -= q->firstnum; /* * If we're only doing 32-bit values, adjust for that again. * Note that this will probably be the wrong thing to if we get * 2**32 messages sent with 32-bit sequence numbers. */ seqnum &= q->mask; /* rule 1: expected sequence number */ expected = (QELEM(q,q->start+q->length-1)+1) & q->mask; if (seqnum == expected) { queue_insert(q, q->start+q->length-1, seqnum); return(GSS_S_COMPLETE); } /* rule 2: > expected sequence number */ if (after(seqnum, expected, q->mask)) { queue_insert(q, q->start+q->length-1, seqnum); if (q->do_replay && !q->do_sequence) return(GSS_S_COMPLETE); else return(GSS_S_GAP_TOKEN); } /* rule 3: seqnum < seqnum(first) */ if (after(QELEM(q,q->start), seqnum, q->mask)) { if (q->do_replay && !q->do_sequence) return(GSS_S_OLD_TOKEN); else return(GSS_S_UNSEQ_TOKEN); } /* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */ else { if (seqnum == QELEM(q,q->start+q->length-1)) return(GSS_S_DUPLICATE_TOKEN); for (i=q->start; istart+q->length-1; i++) { if (seqnum == QELEM(q,i)) return (GSS_S_DUPLICATE_TOKEN); if (after(seqnum, QELEM(q,i), q->mask) && after(QELEM(q,i+1), seqnum, q->mask)) { queue_insert(q, i, seqnum); if (q->do_replay && !q->do_sequence) return (GSS_S_COMPLETE); else return (GSS_S_UNSEQ_TOKEN); } } } /* this should never happen */ return(GSS_S_FAILURE); } void g_order_free(void **vqueue) { queue *q; q = (queue *) (*vqueue); FREE (q, sizeof (queue)); *vqueue = NULL; } /* * These support functions are for the serialization routines */ /*ARGSUSED*/ gss_uint32 g_queue_size(void *vqueue, size_t *sizep) { *sizep += sizeof(queue); return 0; } gss_uint32 g_queue_externalize(void *vqueue, unsigned char **buf, size_t *lenremain) { (void) memcpy(*buf, vqueue, sizeof(queue)); *buf += sizeof(queue); *lenremain -= sizeof(queue); return 0; } gss_uint32 g_queue_internalize(void **vqueue, unsigned char **buf, size_t *lenremain) { void *q; if ((q = (void *) MALLOC(sizeof(queue))) == 0) return ENOMEM; (void) memcpy(q, *buf, sizeof(queue)); *buf += sizeof(queue); *lenremain -= sizeof(queue); *vqueue = q; return 0; } /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" #ifdef HAVE_MEMORY_H #include #endif static const unsigned char zeros[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; krb5_error_code kg_make_seed(context, key, seed) krb5_context context; krb5_keyblock *key; unsigned char *seed; { krb5_error_code code; krb5_keyblock *tmpkey; int i; code = krb5_copy_keyblock(context, key, &tmpkey); if (code) return(code); /* reverse the key bytes, as per spec */ for (i=0; ilength; i++) tmpkey->contents[i] = key->contents[key->length - 1 - i]; code = kg_encrypt(context, tmpkey, KG_USAGE_SEAL, NULL, zeros, seed, 16); krb5_free_keyblock(context, tmpkey); return(code); } /* * Copyright2001 by the Massachusetts Institute of Technology. * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" #include "k5-int.h" /* * $Id: util_seqnum.c 15007 2002-11-15 16:12:20Z epeisach $ */ krb5_error_code kg_make_seq_num(context, key, direction, seqnum, cksum, buf) krb5_context context; krb5_keyblock *key; int direction; krb5_ui_4 seqnum; unsigned char *cksum; unsigned char *buf; { unsigned char plain[8]; plain[4] = direction; plain[5] = direction; plain[6] = direction; plain[7] = direction; if (key->enctype == ENCTYPE_ARCFOUR_HMAC ) { /* Yes, Microsoft used big-endian sequence number.*/ plain[0] = (seqnum>>24) & 0xff; plain[1] = (seqnum>>16) & 0xff; plain[2] = (seqnum>>8) & 0xff; plain[3] = seqnum & 0xff; return kg_arcfour_docrypt (context, key, 0, cksum, 8, &plain[0], 8, buf); } plain[0] = (unsigned char) (seqnum&0xff); plain[1] = (unsigned char) ((seqnum>>8)&0xff); plain[2] = (unsigned char) ((seqnum>>16)&0xff); plain[3] = (unsigned char) ((seqnum>>24)&0xff); 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) krb5_context context; krb5_keyblock *key; unsigned char *cksum; unsigned char *buf; int *direction; krb5_ui_4 *seqnum; { krb5_error_code code; unsigned char plain[8]; if (key->enctype == ENCTYPE_ARCFOUR_HMAC) { code = kg_arcfour_docrypt (context, key, 0, cksum, 8, buf, 8, plain); } else { code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8); } if (code) return(code); if ((plain[4] != plain[5]) || (plain[4] != plain[6]) || (plain[4] != plain[7])) return((krb5_error_code) KG_BAD_SEQ); *direction = plain[4]; if (key->enctype == ENCTYPE_ARCFOUR_HMAC) { *seqnum = (plain[3]|(plain[2]<<8) | (plain[1]<<16)| (plain[0]<<24)); } else { *seqnum = ((plain[0]) | (plain[1]<<8) | (plain[2]<<16) | (plain[3]<<24)); } return(0); } /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 1995 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * $Id: util_set.c 16165 2004-03-14 05:31:43Z raeburn $ */ #include /* SUNW15resync - for MALLOC/FREE */ #include "gssapiP_generic.h" struct _g_set_elt { void *key; void *value; struct _g_set_elt *next; }; int g_set_init(g_set_elt *s) { *s = NULL; return(0); } #if 0 int g_set_destroy(g_set_elt *s) { g_set next; while (*s) { next = (*s)->next; FREE(*s, sizeof(struct _g_set)); *s = next; } return(0); } #endif int g_set_entry_add(g_set_elt *s, void *key, void *value) { g_set_elt first; if ((first = (struct _g_set_elt *) MALLOC(sizeof(struct _g_set_elt))) == NULL) return(ENOMEM); first->key = key; first->value = value; first->next = *s; *s = first; return(0); } int g_set_entry_delete(g_set_elt *s, void *key) { g_set_elt *p; for (p=s; *p; p = &((*p)->next)) { if ((*p)->key == key) { g_set_elt next = (*p)->next; FREE(*p, sizeof(struct _g_set_elt)); *p = next; return(0); } } return(-1); } int g_set_entry_get(g_set_elt *s, void *key, void **value) { g_set_elt p; for (p = *s; p; p = p->next) { if (p->key == key) { *value = p->value; return(0); } } *value = NULL; return(-1); } /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_generic.h" #ifdef _KERNEL #include #else #ifdef HAVE_MEMORY_H #include #endif #include #include #endif /* _KERNEL */ /* * $Id: util_token.c 17987 2006-05-09 11:31:02Z epeisach $ */ /* XXXX this code currently makes the assumption that a mech oid will never be longer than 127 bytes. This assumption is not inherent in the interfaces, so the code can be fixed if the OSI namespace balloons unexpectedly. */ /* Each token looks like this: 0x60 tag for APPLICATION 0, SEQUENCE (constructed, definite-length) possible multiple bytes, need to parse/generate 0x06 tag for OBJECT IDENTIFIER compile-time constant string (assume 1 byte) compile-time constant string the ANY containing the application token bytes 0,1 are the token type bytes 2,n are the token data Note that the token type field is a feature of RFC 1964 mechanisms and is not used by other GSSAPI mechanisms. As such, a token type of -1 is interpreted to mean that no token type should be expected or generated. For the purposes of this abstraction, the token "header" consists of the sequence tag and length octets, the mech OID DER encoding, and the first two inner bytes, which indicate the token type. The token "body" consists of everything else. */ static unsigned int der_length_size(length) int length; { if (length < (1<<7)) return(1); else if (length < (1<<8)) return(2); #if INT_MAX == 0x7fff else return(3); #else else if (length < (1<<16)) return(3); else if (length < (1<<24)) return(4); else return(5); #endif } static void der_write_length(buf, length) unsigned char **buf; int length; { if (length < (1<<7)) { *(*buf)++ = (unsigned char) length; } else { *(*buf)++ = (unsigned char) (der_length_size(length)+127); #if INT_MAX > 0x7fff if (length >= (1<<24)) *(*buf)++ = (unsigned char) (length>>24); if (length >= (1<<16)) *(*buf)++ = (unsigned char) ((length>>16)&0xff); #endif if (length >= (1<<8)) *(*buf)++ = (unsigned char) ((length>>8)&0xff); *(*buf)++ = (unsigned char) (length&0xff); } } /* returns decoded length, or < 0 on failure. Advances buf and decrements bufsize */ static int der_read_length(buf, bufsize) unsigned char **buf; int *bufsize; { unsigned char sf; int ret; if (*bufsize < 1) return(-1); sf = *(*buf)++; (*bufsize)--; if (sf & 0x80) { if ((sf &= 0x7f) > ((*bufsize)-1)) return(-1); if (sf > sizeof(int)) return (-1); ret = 0; for (; sf; sf--) { ret = (ret<<8) + (*(*buf)++); (*bufsize)--; } } else { ret = sf; } return(ret); } /* returns the length of a token, given the mech oid and the body size */ unsigned int g_token_size(mech, body_size) const gss_OID_desc * mech; unsigned int body_size; { /* set body_size to sequence contents size */ body_size += 4 + (int) mech->length; /* NEED overflow check */ return(1 + der_length_size((int) body_size) + body_size); } /* fills in a buffer with the token header. The buffer is assumed to be the right size. buf is advanced past the token header */ void g_make_token_header(mech, body_size, buf, tok_type) const gss_OID_desc * mech; unsigned int body_size; unsigned char **buf; int tok_type; { *(*buf)++ = 0x60; der_write_length(buf, (tok_type == -1) ? 2 : (int) (4 + mech->length + body_size)); *(*buf)++ = 0x06; *(*buf)++ = (unsigned char) mech->length; TWRITE_STR(*buf, mech->elements, mech->length); if (tok_type != -1) { *(*buf)++ = (unsigned char) ((tok_type>>8)&0xff); *(*buf)++ = (unsigned char) (tok_type&0xff); } } /* * Given a buffer containing a token, reads and verifies the token, * leaving buf advanced past the token header, and setting body_size * to the number of remaining bytes. Returns 0 on success, * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the * mechanism in the token does not match the mech argument. buf and * *body_size are left unmodified on error. */ gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize_in, wrapper_required) const gss_OID_desc * mech; unsigned int *body_size; unsigned char **buf_in; int tok_type; unsigned int toksize_in; int wrapper_required; { unsigned char *buf = *buf_in; int seqsize; gss_OID_desc toid; int toksize = toksize_in; if ((toksize-=1) < 0) return(G_BAD_TOK_HEADER); if (*buf++ != 0x60) { if (wrapper_required) return(G_BAD_TOK_HEADER); buf--; toksize++; goto skip_wrapper; } if ((seqsize = der_read_length(&buf, &toksize)) < 0) return(G_BAD_TOK_HEADER); if (seqsize != toksize) return(G_BAD_TOK_HEADER); if ((toksize-=1) < 0) return(G_BAD_TOK_HEADER); if (*buf++ != 0x06) return(G_BAD_TOK_HEADER); if ((toksize-=1) < 0) return(G_BAD_TOK_HEADER); toid.length = *buf++; if ((toksize-=toid.length) < 0) return(G_BAD_TOK_HEADER); toid.elements = buf; buf+=toid.length; if (! g_OID_equal(&toid, mech)) return G_WRONG_MECH; skip_wrapper: if (tok_type != -1) { if ((toksize-=2) < 0) return(G_BAD_TOK_HEADER); if ((*buf++ != ((tok_type>>8)&0xff)) || (*buf++ != (tok_type&0xff))) return(G_WRONG_TOKID); } *buf_in = buf; *body_size = toksize; return 0; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * $Id: util_validate.c 18721 2006-10-16 16:18:29Z epeisach $ */ /* * functions to validate name, credential, and context handles */ #include "gssapiP_generic.h" #ifndef _KERNEL #include "gss_libinit.h" #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef _KERNEL #include #else #include #include #endif #ifdef HAVE_BSD_DB #include #include static const int one = 1; static const DBT dbtone = { (void *) &one, sizeof(one) }; typedef struct _vkey { int type; void *ptr; } vkey; #endif #define V_NAME 1 #define V_CRED_ID 2 #define V_CTX_ID 3 #define V_LCTX_ID 4 /* SUNW15resync beware some of the uses below of type look dubious but seem to have been working in Solaris for a long time */ /* All these functions return 0 on failure, and non-zero on success */ static int g_save(db, type, ptr) g_set *db; int type; void *ptr; { int ret; #ifdef HAVE_BSD_DB DB **vdb; vkey vk; DBT key; #ifndef _KERNEL ret = gssint_initialize_library(); if (ret) return 0; #endif ret = k5_mutex_lock(&db->mutex); if (ret) return 0; vdb = (DB **) &db->data; if (!*vdb) *vdb = dbopen(NULL, O_CREAT|O_RDWR, O_CREAT|O_RDWR, DB_HASH, NULL); vk.type = type; vk.ptr = ptr; key.data = &vk; key.size = sizeof(vk); ret = ((*((*vdb)->put))(*vdb, &key, &dbtone, 0) == 0); (void) k5_mutex_unlock(&db->mutex); return ret; #else g_set_elt *gs; #ifndef _KERNEL ret = gssint_initialize_library(); if (ret) return 0; #endif ret = k5_mutex_lock(&db->mutex); if (ret) return 0; gs = (g_set_elt *) &db->data; if (!*gs) if (g_set_init(gs)) { (void) k5_mutex_unlock(&db->mutex); return(0); } /* SUNW15resync */ ret = (g_set_entry_add(gs, ptr, (void *)(intptr_t)type) == 0); (void) k5_mutex_unlock(&db->mutex); return ret; #endif } static int g_validate(db, type, ptr) g_set *db; int type; void *ptr; { int ret; #ifdef HAVE_BSD_DB DB **vdb; vkey vk; DBT key, value; ret = k5_mutex_lock(&db->mutex); if (ret) return 0; vdb = (DB **) &db->data; if (!*vdb) { (void) k5_mutex_unlock(&db->mutex); return(0); } vk.type = type; vk.ptr = ptr; key.data = &vk; key.size = sizeof(vk); if ((*((*vdb)->get))(*vdb, &key, &value, 0)) { (void) k5_mutex_unlock(&db->mutex); return(0); } (void) k5_mutex_unlock(&db->mutex); return((value.size == sizeof(one)) && (*((int *) value.data) == one)); #else g_set_elt *gs; void *value; ret = k5_mutex_lock(&db->mutex); if (ret) return 0; gs = (g_set_elt *) &db->data; if (!*gs) { (void) k5_mutex_unlock(&db->mutex); return(0); } if (g_set_entry_get(gs, ptr, (void **) &value)) { (void) k5_mutex_unlock(&db->mutex); return(0); } (void) k5_mutex_unlock(&db->mutex); return((intptr_t)value == (intptr_t)type); /* SUNW15resync */ #endif } /*ARGSUSED*/ static int g_delete(db, type, ptr) g_set *db; int type; void *ptr; { int ret; #ifdef HAVE_BSD_DB DB **vdb; vkey vk; DBT key; ret = k5_mutex_lock(&db->mutex); if (ret) return 0; vdb = (DB **) &db->data; if (!*vdb) { (void) k5_mutex_unlock(&db->mutex); return(0); } vk.type = type; vk.ptr = ptr; key.data = &vk; key.size = sizeof(vk); ret = ((*((*vdb)->del))(*vdb, &key, 0) == 0); (void) k5_mutex_unlock(&db->mutex); return ret; #else g_set_elt *gs; ret = k5_mutex_lock(&db->mutex); if (ret) return 0; gs = (g_set_elt *) &db->data; if (!*gs) { (void) k5_mutex_unlock(&db->mutex); return(0); } if (g_set_entry_delete(gs, ptr)) { (void) k5_mutex_unlock(&db->mutex); return(0); } (void) k5_mutex_unlock(&db->mutex); return(1); #endif } /* functions for each type */ /* save */ int g_save_name(vdb, name) g_set *vdb; gss_name_t name; { return(g_save(vdb, V_NAME, (void *) name)); } int g_save_cred_id(vdb, cred) g_set *vdb; gss_cred_id_t cred; { return(g_save(vdb, V_CRED_ID, (void *) cred)); } int g_save_ctx_id(vdb, ctx) g_set *vdb; gss_ctx_id_t ctx; { return(g_save(vdb, V_CTX_ID, (void *) ctx)); } int g_save_lucidctx_id(vdb, lctx) g_set *vdb; void *lctx; { return(g_save(vdb, V_LCTX_ID, (void *) lctx)); } /* validate */ int g_validate_name(vdb, name) g_set *vdb; gss_name_t name; { return(g_validate(vdb, V_NAME, (void *) name)); } int g_validate_cred_id(vdb, cred) g_set *vdb; gss_cred_id_t cred; { return(g_validate(vdb, V_CRED_ID, (void *) cred)); } int g_validate_ctx_id(vdb, ctx) g_set *vdb; gss_ctx_id_t ctx; { return(g_validate(vdb, V_CTX_ID, (void *) ctx)); } int g_validate_lucidctx_id(vdb, lctx) g_set *vdb; void *lctx; { return(g_validate(vdb, V_LCTX_ID, (void *) lctx)); } /* delete */ int g_delete_name(vdb, name) g_set *vdb; gss_name_t name; { return(g_delete(vdb, V_NAME, (void *) name)); } int g_delete_cred_id(vdb, cred) g_set *vdb; gss_cred_id_t cred; { return(g_delete(vdb, V_CRED_ID, (void *) cred)); } int g_delete_ctx_id(vdb, ctx) g_set *vdb; gss_ctx_id_t ctx; { return(g_delete(vdb, V_CTX_ID, (void *) ctx)); } int g_delete_lucidctx_id(vdb, lctx) g_set *vdb; void *lctx; { return(g_delete(vdb, V_LCTX_ID, (void *) lctx)); } /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 1997 by 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. * */ #include "gssapiP_krb5.h" /* * Check to see whether or not a GSSAPI krb5 credential is valid. If * it is not, return an error. */ OM_uint32 krb5_gss_validate_cred_1(OM_uint32 *minor_status, gss_cred_id_t cred_handle, krb5_context context) { krb5_gss_cred_id_t cred; krb5_error_code code; krb5_principal princ; if (!kg_validate_cred_id(cred_handle)) { *minor_status = (OM_uint32) G_VALIDATE_FAILED; return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_DEFECTIVE_CREDENTIAL); } cred = (krb5_gss_cred_id_t) cred_handle; code = k5_mutex_lock(&cred->lock); if (code) { *minor_status = code; return GSS_S_FAILURE; } if (cred->ccache) { if ((code = krb5_cc_get_principal(context, cred->ccache, &princ))) { k5_mutex_unlock(&cred->lock); *minor_status = code; return(GSS_S_DEFECTIVE_CREDENTIAL); } if (!krb5_principal_compare(context, princ, cred->princ)) { k5_mutex_unlock(&cred->lock); *minor_status = KG_CCACHE_NOMATCH; return(GSS_S_DEFECTIVE_CREDENTIAL); } (void)krb5_free_principal(context, princ); } *minor_status = 0; return GSS_S_COMPLETE; } OM_uint32 krb5_gss_validate_cred(minor_status, cred_handle) OM_uint32 *minor_status; gss_cred_id_t cred_handle; { krb5_context context; krb5_error_code code; OM_uint32 maj; code = krb5_gss_init_context(&context); if (code) { *minor_status = code; return GSS_S_FAILURE; } maj = krb5_gss_validate_cred_1(minor_status, cred_handle, context); if (maj == 0) { krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t) cred_handle; k5_mutex_assert_locked(&cred->lock); k5_mutex_unlock(&cred->lock); } else /* Solaris Kerberos - added this else */ save_error_info(*minor_status, context); krb5_free_context(context); return maj; } /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "gssapiP_krb5.h" /* * $Id: verify.c 16171 2004-03-15 17:45:01Z raeburn $ */ /*ARGSUSED*/ OM_uint32 krb5_gss_verify(minor_status, context_handle, message_buffer, token_buffer, qop_state #ifdef _KERNEL , gssd_ctx_verifier #endif ) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t message_buffer; gss_buffer_t token_buffer; int *qop_state; #ifdef _KERNEL OM_uint32 gssd_ctx_verifier; #endif { return(kg_unseal(minor_status, context_handle, token_buffer, message_buffer, NULL, qop_state, KG_TOK_SIGN_MSG)); } /* V2 interface */ OM_uint32 krb5_gss_verify_mic(minor_status, context_handle, message_buffer, token_buffer, qop_state) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t message_buffer; gss_buffer_t token_buffer; gss_qop_t *qop_state; { OM_uint32 rstat; int qstate; rstat = kg_unseal(minor_status, context_handle, token_buffer, message_buffer, NULL, &qstate, KG_TOK_MIC_MSG); if (!rstat && qop_state) *qop_state = (gss_qop_t) qstate; return(rstat); } /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * 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 * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of OpenVision not be used * in advertising or publicity pertaining to distribution of the software * 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 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. * * Export of this software from the United States of America may require * a specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of FundsXpress. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. FundsXpress makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "gssapiP_krb5.h" size_t KRB5_CALLCONV krb5_encrypt_size(size_t, krb5_enctype); /* SUNW15resync - XXX find new home for this func */ #ifdef _KERNEL size_t KRB5_CALLCONV krb5_encrypt_size(size_t length, krb5_enctype crypto) { size_t ret; if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret)) /*LINTED*/ return(-1); /* XXX */ return(ret); } #endif /* V2 interface */ OM_uint32 krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, qop_req, req_output_size, max_input_size) OM_uint32 *minor_status; gss_ctx_id_t context_handle; int conf_req_flag; gss_qop_t qop_req; OM_uint32 req_output_size; OM_uint32 *max_input_size; { krb5_gss_ctx_id_rec *ctx; OM_uint32 data_size, conflen; OM_uint32 ohlen; int overhead; /* Solaris Kerb - check to make sure we aren't writing to a NULL pointer */ if (!max_input_size) return(GSS_S_CALL_INACCESSIBLE_WRITE); /* only default qop is allowed */ /* * SUNW15resync * mit 1.2-6: if (qop_req != GSS_C_QOP_DEFAULT) { * Go with Solaris version here, though not sure which is * correct and RFC 2743 does not make it clear. */ if ((qop_req & GSS_KRB5_CONF_C_QOP_MASK) != GSS_C_QOP_DEFAULT) { *minor_status = (OM_uint32) G_UNKNOWN_QOP; /* SUNW15resync - RFC 2743 is clear here but this is still GSS_S_FAILURE in MIT */ return(GSS_S_BAD_QOP); } /* 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 (ctx->proto == 1) { /* No pseudo-ASN.1 wrapper overhead, so no sequence length and OID. */ OM_uint32 sz = req_output_size; /* Token header: 16 octets. */ if (conf_req_flag) { while (sz > 0 && krb5_encrypt_size(sz, ctx->enc->enctype) + 16 > req_output_size) sz--; /* Allow for encrypted copy of header. */ if (sz > 16) sz -= 16; else sz = 0; #ifdef CFX_EXERCISE /* Allow for EC padding. In the MIT implementation, only added while testing. */ if (sz > 65535) sz -= 65535; else sz = 0; #endif } else { /* Allow for token header and checksum. */ if (sz < 16 + ctx->cksum_size) sz = 0; else sz -= (16 + ctx->cksum_size); } *max_input_size = sz; *minor_status = 0; return GSS_S_COMPLETE; } /* 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(ctx->k5_context, ctx->enc); data_size = (conflen + data_size + 8) & (~(OM_uint32)7); ohlen = g_token_size(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); }