1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* #pragma ident "@(#)g_canon_name.c 1.15 04/02/23 SMI" */ 7 8 /* 9 * routine gss_canonicalize_name 10 * 11 * This routine is used to produce a mechanism specific 12 * representation of name that has been previously 13 * imported with gss_import_name. The routine uses the mechanism 14 * specific implementation of gss_import_name to implement this 15 * function. 16 * 17 * We allow a NULL output_name, in which case we modify the 18 * input_name to include the mechanism specific name. 19 */ 20 21 #include <mglueP.h> 22 #ifdef HAVE_STDLIB_H 23 #include <stdlib.h> 24 #endif 25 #include <string.h> 26 #include <errno.h> 27 28 static OM_uint32 29 val_canon_name_args( 30 OM_uint32 *minor_status, 31 const gss_name_t input_name, 32 const gss_OID mech_type, 33 gss_name_t *output_name) 34 { 35 36 /* Initialize outputs. */ 37 38 if (minor_status != NULL) 39 *minor_status = 0; 40 41 if (output_name != NULL) 42 *output_name = GSS_C_NO_NAME; 43 44 /* Validate arguments. */ 45 46 if (minor_status == NULL) 47 return (GSS_S_CALL_INACCESSIBLE_WRITE); 48 49 if (input_name == GSS_C_NO_NAME || mech_type == GSS_C_NULL_OID) 50 return (GSS_S_CALL_INACCESSIBLE_READ); 51 52 return (GSS_S_COMPLETE); 53 } 54 55 56 OM_uint32 KRB5_CALLCONV 57 gss_canonicalize_name(minor_status, 58 input_name, 59 mech_type, 60 output_name) 61 OM_uint32 *minor_status; 62 const gss_name_t input_name; 63 const gss_OID mech_type; 64 gss_name_t *output_name; 65 { 66 gss_union_name_t in_union, out_union = NULL, dest_union = NULL; 67 OM_uint32 major_status = GSS_S_FAILURE, tmpmin; 68 gss_OID selected_mech; 69 70 major_status = val_canon_name_args(minor_status, 71 input_name, 72 mech_type, 73 output_name); 74 if (major_status != GSS_S_COMPLETE) 75 return (major_status); 76 77 major_status = gssint_select_mech_type(minor_status, mech_type, 78 &selected_mech); 79 if (major_status != GSS_S_COMPLETE) 80 return (major_status); 81 82 /* Initial value needed below. */ 83 major_status = GSS_S_FAILURE; 84 85 in_union = (gss_union_name_t)input_name; 86 /* 87 * If the caller wants to reuse the name, and the name has already 88 * been converted, then there is nothing for us to do. 89 */ 90 if (!output_name && in_union->mech_type && 91 g_OID_equal(in_union->mech_type, selected_mech)) 92 return (GSS_S_COMPLETE); 93 94 /* ok, then we need to do something - start by creating data struct */ 95 if (output_name) { 96 out_union = 97 (gss_union_name_t)malloc(sizeof (gss_union_name_desc)); 98 if (!out_union) 99 goto allocation_failure; 100 101 out_union->mech_type = 0; 102 out_union->mech_name = 0; 103 out_union->name_type = 0; 104 out_union->external_name = 0; 105 out_union->loopback = out_union; 106 107 /* Allocate the buffer for the user specified representation */ 108 if (gssint_create_copy_buffer(in_union->external_name, 109 &out_union->external_name, 1)) 110 goto allocation_failure; 111 112 if (in_union->name_type != GSS_C_NULL_OID) { 113 major_status = generic_gss_copy_oid(minor_status, 114 in_union->name_type, 115 &out_union->name_type); 116 if (major_status) { 117 map_errcode(minor_status); 118 goto allocation_failure; 119 } 120 } 121 122 } 123 124 /* 125 * might need to delete any old mechanism names if we are 126 * reusing the buffer. 127 */ 128 if (!output_name) { 129 if (in_union->mech_type) { 130 (void) gssint_release_internal_name(minor_status, 131 in_union->mech_type, 132 &in_union->mech_name); 133 (void) gss_release_oid(minor_status, 134 &in_union->mech_type); 135 in_union->mech_type = 0; 136 } 137 dest_union = in_union; 138 } else 139 dest_union = out_union; 140 141 /* now let's create the new mech name */ 142 if ((major_status = generic_gss_copy_oid(minor_status, selected_mech, 143 &dest_union->mech_type))) { 144 map_errcode(minor_status); 145 goto allocation_failure; 146 } 147 148 if ((major_status = 149 gssint_import_internal_name(minor_status, selected_mech, 150 in_union, 151 &dest_union->mech_name))) 152 goto allocation_failure; 153 154 if (output_name) 155 *output_name = (gss_name_t)dest_union; 156 157 return (GSS_S_COMPLETE); 158 159 allocation_failure: 160 if (out_union) { 161 /* Release the partly constructed out_union. */ 162 gss_name_t name = (gss_name_t)out_union; 163 (void) gss_release_name(&tmpmin, &name); 164 } else if (!output_name) { 165 /* Release only the mech name fields in in_union. */ 166 if (in_union->mech_name) { 167 (void) gssint_release_internal_name(&tmpmin, 168 dest_union->mech_type, 169 &dest_union->mech_name); 170 } 171 if (in_union->mech_type) 172 (void) gss_release_oid(&tmpmin, &dest_union->mech_type); 173 } 174 175 return (major_status); 176 } /********** gss_canonicalize_name ********/ 177