Sdiff g_glue.c
  1 /*
  2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  3  * Use is subject to license terms.
  4  */
  5 
  6 #pragma ident   "@(#)g_glue.c   1.26    04/09/08 SMI" 
  7 
  8 #include <mechglueP.h>
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <strings.h>
 12 #include <errno.h>
 13 
 14 #define MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
 15 
 16 /*
 17  * This file contains the support routines for the glue layer.
 18  */
 19 
 20 /*


























































 21  * der_length_size: Return the number of bytes to encode a given length.
 22  */
 23 unsigned int
 24 der_length_size(unsigned int len)
 25 {
 26    if (length < (1<<7)) 


 27       return(1);
 28    else if (length < (1<<8)) 
 29       return(2); 
 30 #if (SIZEOF_INT == 2) 
 31    else  
 32        return(3); 
 33 #else    
 34    else if (length < (1<<16)) 
 35       return(3); 
 36    else if (length < (1<<24)) 
 37       return(4); 
 38    else  
 39       return(5); 
 40 #endif   
 41 }
 42 



 43 /*































































 44  *  glue routine for get_mech_type
 45  *
 46  */
 47 OM_uint32
 48 __gss_get_mech_type(OID, token)
 49         gss_OID                 OID;
 50         const gss_buffer_t      token;
 51 {
 52         unsigned char *buffer_ptr;
 53         int length;
 54 
 55         /*
 56          * This routine reads the prefix of "token" in order to determine
 57          * its mechanism type. It assumes the encoding suggested in
 58          * Appendix B of RFC 1508. This format starts out as follows :
 59          *
 60          * tag for APPLICATION 0, Sequence[constructed, definite length]
 61          * length of remainder of token
 62          * tag of OBJECT IDENTIFIER
 63          * length of mechanism OID
 64          * encoding of mechanism OID
 65          * <the rest of the token>
 66          *
 67          * Numerically, this looks like :
 68          *
 69          * 0x60
 70          * <length> - could be multiple bytes
 71          * 0x06
 72          * <length> - assume only one byte, hence OID length < 127
 73          * <mech OID bytes>
 74          *
 75          * The routine fills in the OID value and returns an error as necessary.
 76          */
 77 
 78         if (token == NULL) 



 79                 return (GSS_S_DEFECTIVE_TOKEN);
 80 
 81         /* Skip past the APP/Sequnce byte and the token length */
 82 
 83         buffer_ptr = (unsigned char *) token->value;
 84 
 85         if (*(buffer_ptr++) != 0x60)
 86                 return (GSS_S_DEFECTIVE_TOKEN);
 87         length = *buffer_ptr++;





 88         if (length & 0x80) {
 89                 if ((length & 0x7f) > 4)
 90                         return (GSS_S_DEFECTIVE_TOKEN);
 91                 buffer_ptr += length & 0x7f;
 92         }
 93 
 94         if (*(buffer_ptr++) != 0x06)
 95                 return (GSS_S_DEFECTIVE_TOKEN);
 96 
 97         OID->length = (OM_uint32) *(buffer_ptr++);
 98         OID->elements = (void *) buffer_ptr;
 99         return (GSS_S_COMPLETE);
100 }
101 
102 
103 /*
104  *  Internal routines to get and release an internal mechanism name
105  */
106 OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
107                                         internal_name)
108 OM_uint32               *minor_status;
109 const gss_OID           mech_type;
110 gss_union_name_t        union_name;
111 gss_name_t              *internal_name;
112 {
113         OM_uint32                       status;
114         gss_mechanism           mech;
115 
116         mech = __gss_get_mechanism(mech_type);
117         if (mech) {
118                 if (mech->gss_import_name)
119                         status = mech->gss_import_name(
120                                                 mech->context,
121                                                 minor_status,
122                                                 union_name->external_name,
123                                                 union_name->name_type,
124                                                 internal_name);
125                 else
126                         status = GSS_S_BAD_BINDINGS; 
127 
128                 return (status);
129         }
130 
131         return (GSS_S_BAD_MECH);
132 }
133 























































































































134 OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
135                                                 external_name, name_type)
136 OM_uint32               *minor_status;
137 const gss_OID           mech_type;
138 const gss_name_t        internal_name;
139 gss_buffer_t            external_name;
140 gss_OID                 *name_type;
141 {
142         OM_uint32                       status;
143         gss_mechanism           mech;
144 
145         mech = __gss_get_mechanism(mech_type);
146         if (mech) {
147                 if (mech->gss_display_name)
148                         status = mech->gss_display_name(
149                                                         mech->context,
150                                                         minor_status,
151                                                         internal_name,
152                                                         external_name,
153                                                         name_type);
154                 else
155                         status = GSS_S_BAD_BINDINGS; 
156 
157                 return (status);
158         }
159 
160         return (GSS_S_BAD_MECH);
161 }
162 
163 OM_uint32
164 __gss_release_internal_name(minor_status, mech_type, internal_name)
165 OM_uint32               *minor_status;
166 const gss_OID           mech_type;
167 gss_name_t              *internal_name;
168 {
169         OM_uint32                       status;
170         gss_mechanism           mech;
171 
172         mech = __gss_get_mechanism(mech_type);
173         if (mech) {
174                 if (mech->gss_release_name)
175                         status = mech->gss_release_name(
176                                                         mech->context,
177                                                         minor_status,
178                                                         internal_name);
179                 else
180                         status = GSS_S_BAD_BINDINGS; 
181 
182                 return (status);
183         }
184 
185         return (GSS_S_BAD_MECH);
186 }
187 
188 
189 /*
190  * This function converts an internal gssapi name to a union gssapi
191  * name.  Note that internal_name should be considered "consumed" by
192  * this call, whether or not we return an error.
193  */
194 OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
195                                                 internal_name, external_name)
196         OM_uint32 *minor_status;
197         gss_mechanism           mech;
198         gss_name_t              internal_name;
199         gss_name_t              *external_name;
200 {
201         OM_uint32 major_status, tmp;
202         gss_union_name_t union_name;
203 
204         union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
205         if (!union_name) {
206                         *minor_status = ENOMEM; 
207                         goto allocation_failure;
208         }
209         union_name->mech_type = 0;
210         union_name->mech_name = internal_name;
211         union_name->name_type = 0;
212         union_name->external_name = 0;
213 
214         major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
215                                                 &union_name->mech_type);
216         if (major_status != GSS_S_COMPLETE)
217                 goto allocation_failure;
218 
219         union_name->external_name =
220                 (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
221         if (!union_name->external_name) {
222                         *minor_status = ENOMEM; 
223                         goto allocation_failure;
224         }
225 
226         major_status = mech->gss_display_name(mech->context, minor_status,
227                                                 internal_name,
228                                                 union_name->external_name,
229                                                 &union_name->name_type);
230         if (major_status != GSS_S_COMPLETE)
231                 goto allocation_failure;
232 
233         *external_name =  (gss_name_t)union_name;
234         return (GSS_S_COMPLETE);
235 
236 allocation_failure:
237         if (union_name) {
238                 if (union_name->external_name) {
239                         if (union_name->external_name->value)
240                                 free(union_name->external_name->value);
241                         free(union_name->external_name);
242                 }
243                 if (union_name->name_type)
244                         (void) gss_release_oid(&tmp, &union_name->name_type);
245                 if (union_name->mech_name) 
246                 (void) __gss_release_internal_name(minor_status, 
247                         union_name->mech_type, &union_name->mech_name); 
248                 if (union_name->mech_type)
249                         (void) gss_release_oid(&tmp, &union_name->mech_type);
250                 free(union_name);
251         }







252 
253         return (major_status);
254 }
255 
256 /*
257  * Glue routine for returning the mechanism-specific credential from a
258  * external union credential.
259  */
260 gss_cred_id_t
261 __gss_get_mechanism_cred(union_cred, mech_type)
262         const gss_union_cred_t  union_cred;
263         const gss_OID           mech_type;
264 {
265         int                     i;
266 
267         if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
268                 return (GSS_C_NO_CREDENTIAL);
269 
270         for (i = 0; i < union_cred->count; i++) {
271                 if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
272                         return (union_cred->cred_array[i]);
273         }
274         return (GSS_C_NO_CREDENTIAL);
275 }
276 












































  1 /*
  2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  3  * Use is subject to license terms.
  4  */
  5 
  6 #pragma ident   "@(#)g_glue.c   1.25    04/02/23 SMI" 
  7 
  8 #include <mechglueP.h>
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <strings.h>
 12 #include <errno.h>
 13 
 14 #define MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
 15 
 16 /*
 17  * This file contains the support routines for the glue layer.
 18  */
 19 
 20 /*
 21  * get_der_length: Givin a pointer to a buffer that contains a DER encoded
 22  * length, decode the length updating the buffer to point to the character
 23  * after the DER encoding. The parameter bytes will point to the number of
 24  * bytes that made up the DER encoding of the length originally pointed to
 25  * by the buffer. Note we return -1 on error.
 26  */
 27 int
 28 get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
 29 {
 30         /* p points to the beginning of the buffer */
 31         unsigned char *p = *buf;
 32         int length, new_length;
 33         int octets;
 34 
 35         if (buf_len < 1)
 36                 return (-1);
 37 
 38         /* We should have at least one byte */
 39         *bytes = 1;
 40 
 41         /*
 42          * If the High order bit is not set then the length is just the value
 43          * of *p.
 44          */
 45         if (*p < 128) {
 46                 *buf = p+1;     /* Advance the buffer */
 47         return (*p);            /* return the length */
 48         }
 49 
 50         /*
 51          * if the High order bit is set, then the low order bits represent
 52          * the number of bytes that contain the DER encoding of the length.
 53          */
 54 
 55         octets = *p++ & 0x7f;
 56         *bytes += octets;
 57 
 58         /* See if the supplied buffer contains enough bytes for the length. */
 59         if (octets > buf_len - 1)
 60                 return (-1);
 61 
 62         /*
 63          * Calculate a multibyte length. The length is encoded as an
 64          * unsigned integer base 256.
 65          */
 66         for (length = 0; octets; octets--) {
 67                 new_length = (length << 8) + *p++;
 68                 if (new_length < length)  /* overflow */
 69                         return (-1);
 70                 length = new_length;
 71         }
 72 
 73         *buf = p; /* Advance the buffer */
 74 
 75         return (length);
 76 }
 77 
 78 /*
 79  * der_length_size: Return the number of bytes to encode a given length.
 80  */
 81 unsigned int
 82 der_length_size(unsigned int len)
 83 {
 84         int i; 
 85  
 86         if (len < 128) 
 87                 return (1);
 88  
 89         for (i = 0; len; i++) { 
 90                 len >>= 8; 










 91         }
 92 
 93         return (i+1);
 94 }
 95 
 96 /*
 97  * put_der_length: Encode the supplied length into the buffer pointed to
 98  * by buf. max_length represents the maximum length of the buffer pointed
 99  * to by buff. We will advance buf to point to the character after the newly
100  * DER encoded length. We return 0 on success or -l it the length cannot
101  * be encoded in max_len characters.
102  */
103 int
104 put_der_length(unsigned length, unsigned char **buf, unsigned int max_len)
105 {
106         unsigned char *s = *buf, *p;
107         unsigned int buf_len = 0;
108         int i, first;
109 
110         /* Oops */
111         if (buf == 0 || max_len < 1)
112                 return (-1);
113 
114         /* Single byte is the length */
115         if (length < 128) {
116                 *s++ = length;
117                 *buf = s;
118                 return (0);
119         }
120 
121         /* First byte contains the number of octets */
122         p = s + 1;
123 
124         /* Running total of the DER encoding length */
125         buf_len = 0;
126 
127         /*
128          * Encode MSB first. We do the encoding by setting a shift
129          * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
130          * by the factor. We then encode the resulting low order byte.
131          * We subtract 8 from the shift factor and repeat to ecnode the next
132          * byte. We stop when the shift factor is zero or we've run out of
133          * buffer to encode into.
134          */
135         first = 0;
136         for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
137                 unsigned int v;
138                 v = (length >> i) & 0xff;
139                 if ((v) || first) {
140                         buf_len += 1;
141                         *p++ = v;
142                         first = 1;
143                 }
144         }
145         if (i >= 0)                  /* buffer overflow */
146                 return (-1);
147 
148         /*
149          * We go back now and set the first byte to be the length with
150          * the high order bit set.
151          */
152         *s = buf_len | 0x80;
153         *buf = p;
154 
155         return (0);
156 }
157 
158 
159 /*
160  *  glue routine for get_mech_type
161  *
162  */
163 OM_uint32
164 __gss_get_mech_type(OID, token)
165         gss_OID                 OID;
166         const gss_buffer_t      token;
167 {
168         unsigned char *buffer_ptr;
169         int length;
170 
171         /*
172          * This routine reads the prefix of "token" in order to determine
173          * its mechanism type. It assumes the encoding suggested in
174          * Appendix B of RFC 1508. This format starts out as follows :
175          *
176          * tag for APPLICATION 0, Sequence[constructed, definite length]
177          * length of remainder of token
178          * tag of OBJECT IDENTIFIER
179          * length of mechanism OID
180          * encoding of mechanism OID
181          * <the rest of the token>
182          *
183          * Numerically, this looks like :
184          *
185          * 0x60
186          * <length> - could be multiple bytes
187          * 0x06
188          * <length> - assume only one byte, hence OID length < 127
189          * <mech OID bytes>
190          *
191          * The routine fills in the OID value and returns an error as necessary.
192          */
193 
194         if (OID == NULL) 
195                 return (GSS_S_CALL_INACCESSIBLE_WRITE); 
196  
197         if ((token == NULL) || (token->value == NULL)) 
198                 return (GSS_S_DEFECTIVE_TOKEN);
199 
200         /* Skip past the APP/Sequnce byte and the token length */
201 
202         buffer_ptr = (unsigned char *) token->value;
203 
204         if (*(buffer_ptr++) != 0x60)
205                 return (GSS_S_DEFECTIVE_TOKEN);
206         length = *buffer_ptr++;
207 
208         /* check if token length is null */
209         if (length == 0)
210             return (GSS_S_DEFECTIVE_TOKEN);
211 
212         if (length & 0x80) {
213                 if ((length & 0x7f) > 4)
214                         return (GSS_S_DEFECTIVE_TOKEN);
215                 buffer_ptr += length & 0x7f;
216         }
217 
218         if (*(buffer_ptr++) != 0x06)
219                 return (GSS_S_DEFECTIVE_TOKEN);
220 
221         OID->length = (OM_uint32) *(buffer_ptr++);
222         OID->elements = (void *) buffer_ptr;
223         return (GSS_S_COMPLETE);
224 }
225 
226 
227 /*
228  *  Internal routines to get and release an internal mechanism name
229  */
230 OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
231                                         internal_name)
232 OM_uint32               *minor_status;
233 const gss_OID           mech_type;
234 gss_union_name_t        union_name;
235 gss_name_t              *internal_name;
236 {
237         OM_uint32                       status;
238         gss_mechanism           mech;
239 
240         mech = __gss_get_mechanism(mech_type);
241         if (mech) {
242                 if (mech->gss_import_name)
243                         status = mech->gss_import_name(
244                                                 mech->context,
245                                                 minor_status,
246                                                 union_name->external_name,
247                                                 union_name->name_type,
248                                                 internal_name);
249                 else
250                         status = GSS_S_UNAVAILABLE; 
251 
252                 return (status);
253         }
254 
255         return (GSS_S_BAD_MECH);
256 }
257 
258 
259 OM_uint32 __gss_export_internal_name(minor_status, mech_type,
260                 internal_name, name_buf)
261 OM_uint32               *minor_status;
262 const gss_OID           mech_type;
263 const gss_name_t        internal_name;
264 gss_buffer_t            name_buf;
265 {
266         OM_uint32 status;
267         gss_mechanism mech;
268         gss_buffer_desc dispName;
269         gss_OID nameOid;
270         unsigned char *buf = NULL;
271         const unsigned char tokId[] = "\x04\x01";
272         const int tokIdLen = 2;
273         const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
274         int mechOidDERLen = 0;
275         int mechOidLen = 0;
276 
277         mech = __gss_get_mechanism(mech_type);
278         if (!mech)
279                 return (GSS_S_BAD_MECH);
280 
281         if (mech->gss_export_name)
282                 return (mech->gss_export_name(mech->context,
283                                                 minor_status,
284                                                 internal_name,
285                                                 name_buf));
286 
287         /*
288          * if we are here it is because the mechanism does not provide
289          * a gss_export_name so we will use our implementation.  We
290          * do required that the mechanism define a gss_display_name.
291          */
292         if (!mech->gss_display_name)
293                 return (GSS_S_UNAVAILABLE);
294 
295         /*
296          * NOTE: RFC2743 (section 3.2) governs the format of the outer
297          *       wrapper of exported names; the mechanisms' specs govern
298          *       the format of the inner portion of the exported name
299          *       and, for some (e.g., RFC1964, the Kerberos V mech), a
300          *       generic default as implemented here will do.
301          *
302          * The outer wrapper of an exported MN is: 2-octet tok Id
303          * (0x0401) + 2-octet network-byte order mech OID length + mech
304          * oid (in DER format, including DER tag and DER length) +
305          * 4-octet network-byte order length of inner portion + inner
306          * portion.
307          *
308          * For the Kerberos V mechanism the inner portion of an exported
309          * MN is the display name string and ignores the name type OID
310          * altogether.  And we hope this will be so for any future
311          * mechanisms also, so that factoring name export/import out of
312          * the mech and into libgss pays off.
313          */
314         if ((status = mech->gss_display_name(mech->context,
315                                                 minor_status,
316                                                 internal_name,
317                                                 &dispName,
318                                                 &nameOid))
319                                                 != GSS_S_COMPLETE)
320                 return (status);
321 
322         /* determine the size of the buffer needed */
323         mechOidDERLen = der_length_size(mech_type->length);
324         name_buf->length = tokIdLen + mechOidLenLen +
325                                 mechOidTagLen + mechOidDERLen +
326                                 mech_type->length +
327                                 nameLenLen + dispName.length;
328         if ((name_buf->value = (void*)malloc(name_buf->length)) ==
329                 (void*)NULL) {
330                         name_buf->length = 0;
331                         (void) gss_release_buffer(&status, &dispName);
332                         return (GSS_S_FAILURE);
333         }
334 
335         /* now create the name ..... */
336         buf = (unsigned char *)name_buf->value;
337         (void) memset(name_buf->value, 0, name_buf->length);
338         (void) memcpy(buf, tokId, tokIdLen);
339         buf += tokIdLen;
340 
341         /* spec allows only 2 bytes for the mech oid length */
342         mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
343         *buf++ = (mechOidLen & 0xFF00) >> 8;
344         *buf++ = (mechOidLen & 0x00FF);
345 
346         /*
347          * DER Encoding of mech OID contains OID Tag (0x06), length and
348          * mech OID value
349         */
350         *buf++ = 0x06;
351         if (put_der_length(mech_type->length, &buf,
352                 (name_buf->length - tokIdLen -2)) != 0) {
353                 name_buf->length = 0;
354                 free(name_buf->value);
355                 (void) gss_release_buffer(&status, &dispName);
356                 return (GSS_S_FAILURE);
357         }
358 
359         (void) memcpy(buf, mech_type->elements, mech_type->length);
360         buf += mech_type->length;
361 
362         /* spec designates the next 4 bytes for the name length */
363         *buf++ = (dispName.length & 0xFF000000) >> 24;
364         *buf++ = (dispName.length & 0x00FF0000) >> 16;
365         *buf++ = (dispName.length & 0x0000FF00) >> 8;
366         *buf++ = (dispName.length & 0X000000FF);
367 
368         /* for the final ingredient - add the name from gss_display_name */
369         (void) memcpy(buf, dispName.value, dispName.length);
370 
371         /* release the buffer obtained from gss_display_name */
372         (void) gss_release_buffer(minor_status, &dispName);
373         return (GSS_S_COMPLETE);
374 } /*  __gss_export_internal_name */
375 
376 
377 OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
378                                                 external_name, name_type)
379 OM_uint32               *minor_status;
380 const gss_OID           mech_type;
381 const gss_name_t        internal_name;
382 gss_buffer_t            external_name;
383 gss_OID                 *name_type;
384 {
385         OM_uint32                       status;
386         gss_mechanism           mech;
387 
388         mech = __gss_get_mechanism(mech_type);
389         if (mech) {
390                 if (mech->gss_display_name)
391                         status = mech->gss_display_name(
392                                                         mech->context,
393                                                         minor_status,
394                                                         internal_name,
395                                                         external_name,
396                                                         name_type);
397                 else
398                         status = GSS_S_UNAVAILABLE; 
399 
400                 return (status);
401         }
402 
403         return (GSS_S_BAD_MECH);
404 }
405 
406 OM_uint32
407 __gss_release_internal_name(minor_status, mech_type, internal_name)
408 OM_uint32               *minor_status;
409 const gss_OID           mech_type;
410 gss_name_t              *internal_name;
411 {
412         OM_uint32                       status;
413         gss_mechanism           mech;
414 
415         mech = __gss_get_mechanism(mech_type);
416         if (mech) {
417                 if (mech->gss_release_name)
418                         status = mech->gss_release_name(
419                                                         mech->context,
420                                                         minor_status,
421                                                         internal_name);
422                 else
423                         status = GSS_S_UNAVAILABLE; 
424 
425                 return (status);
426         }
427 
428         return (GSS_S_BAD_MECH);
429 }
430 
431 
432 /*
433  * This function converts an internal gssapi name to a union gssapi
434  * name.  Note that internal_name should be considered "consumed" by
435  * this call, whether or not we return an error.
436  */
437 OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
438                                                 internal_name, external_name)
439         OM_uint32 *minor_status;
440         gss_mechanism           mech;
441         gss_name_t              internal_name;
442         gss_name_t              *external_name;
443 {
444         OM_uint32 major_status, tmp;
445         gss_union_name_t union_name;
446 
447         union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
448         if (!union_name) {

449                         goto allocation_failure;
450         }
451         union_name->mech_type = 0;
452         union_name->mech_name = internal_name;
453         union_name->name_type = 0;
454         union_name->external_name = 0;
455 
456         major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
457                                                 &union_name->mech_type);
458         if (major_status != GSS_S_COMPLETE)
459                 goto allocation_failure;
460 
461         union_name->external_name =
462                 (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
463         if (!union_name->external_name) {

464                         goto allocation_failure;
465         }
466 
467         major_status = mech->gss_display_name(mech->context, minor_status,
468                                                 internal_name,
469                                                 union_name->external_name,
470                                                 &union_name->name_type);
471         if (major_status != GSS_S_COMPLETE)
472                 goto allocation_failure;
473 
474         *external_name =  (gss_name_t)union_name;
475         return (GSS_S_COMPLETE);
476 
477 allocation_failure:
478         if (union_name) {
479                 if (union_name->external_name) {
480                         if (union_name->external_name->value)
481                                 free(union_name->external_name->value);
482                         free(union_name->external_name);
483                 }
484                 if (union_name->name_type)
485                         (void) gss_release_oid(&tmp, &union_name->name_type);



486                 if (union_name->mech_type)
487                         (void) gss_release_oid(&tmp, &union_name->mech_type);
488                 free(union_name);
489         }
490         /*
491          * do as the top comment says - since we are now owners of
492          * internal_name, we must clean it up
493          */
494         if (internal_name)
495                 (void) __gss_release_internal_name(&tmp, &mech->mech_type,
496                                                 &internal_name);
497 
498         return (major_status);
499 }
500 
501 /*
502  * Glue routine for returning the mechanism-specific credential from a
503  * external union credential.
504  */
505 gss_cred_id_t
506 __gss_get_mechanism_cred(union_cred, mech_type)
507         const gss_union_cred_t  union_cred;
508         const gss_OID           mech_type;
509 {
510         int                     i;
511 
512         if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
513                 return (GSS_C_NO_CREDENTIAL);
514 
515         for (i = 0; i < union_cred->count; i++) {
516                 if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
517                         return (union_cred->cred_array[i]);
518         }
519         return (GSS_C_NO_CREDENTIAL);
520 }
521 
522 
523 /*
524  * Routine to create and copy the gss_buffer_desc structure.
525  * Both space for the structure and the data is allocated.
526  */
527 OM_uint32
528 __gss_create_copy_buffer(srcBuf, destBuf, addNullChar)
529         const gss_buffer_t      srcBuf;
530         gss_buffer_t            *destBuf;
531         int                     addNullChar;
532 {
533         gss_buffer_t aBuf;
534         int len;
535 
536         if (destBuf == NULL)
537                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
538 
539         *destBuf = 0;
540 
541         aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
542         if (!aBuf)
543                 return (GSS_S_FAILURE);
544 
545         if (addNullChar)
546                 len = srcBuf->length + 1;
547         else
548                 len = srcBuf->length;
549 
550         if (!(aBuf->value = (void*)malloc(len))) {
551                 free(aBuf);
552                 return (GSS_S_FAILURE);
553         }
554 
555 
556         (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
557         aBuf->length = srcBuf->length;
558         *destBuf = aBuf;
559 
560         /* optionally add a NULL character */
561         if (addNullChar)
562                 ((char *)aBuf->value)[aBuf->length] = '\0';
563 
564         return (GSS_S_COMPLETE);
565 } /* ****** __gss_create_copy_buffer  ****** */