Blame src/lib/gssapi/mechglue/g_acquire_cred_with_pw.c

Packit Service 99d1c0
/* #pragma ident	"@(#)g_acquire_cred.c	1.22	04/02/23 SMI" */
Packit Service 99d1c0
Packit Service 99d1c0
/*
Packit Service 99d1c0
 * Copyright 1996 by Sun Microsystems, Inc.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * Permission to use, copy, modify, distribute, and sell this software
Packit Service 99d1c0
 * and its documentation for any purpose is hereby granted without fee,
Packit Service 99d1c0
 * provided that the above copyright notice appears in all copies and
Packit Service 99d1c0
 * that both that copyright notice and this permission notice appear in
Packit Service 99d1c0
 * supporting documentation, and that the name of Sun Microsystems not be used
Packit Service 99d1c0
 * in advertising or publicity pertaining to distribution of the software
Packit Service 99d1c0
 * without specific, written prior permission. Sun Microsystems makes no
Packit Service 99d1c0
 * representations about the suitability of this software for any
Packit Service 99d1c0
 * purpose.  It is provided "as is" without express or implied warranty.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit Service 99d1c0
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit Service 99d1c0
 * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit Service 99d1c0
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
Packit Service 99d1c0
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
Packit Service 99d1c0
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit Service 99d1c0
 * PERFORMANCE OF THIS SOFTWARE.
Packit Service 99d1c0
 */
Packit Service 99d1c0
Packit Service 99d1c0
/*
Packit Service 99d1c0
 *  glue routine for gss_acquire_cred_with_password
Packit Service 99d1c0
 */
Packit Service 99d1c0
Packit Service 99d1c0
#include "mglueP.h"
Packit Service 99d1c0
#include <stdio.h>
Packit Service 99d1c0
#ifdef HAVE_STDLIB_H
Packit Service 99d1c0
#include <stdlib.h>
Packit Service 99d1c0
#endif
Packit Service 99d1c0
#include <string.h>
Packit Service 99d1c0
#include <errno.h>
Packit Service 99d1c0
#include <time.h>
Packit Service 99d1c0
Packit Service 99d1c0
static OM_uint32
Packit Service 99d1c0
val_acq_cred_pw_args(
Packit Service 99d1c0
    OM_uint32 *minor_status,
Packit Service 99d1c0
    const gss_name_t desired_name,
Packit Service 99d1c0
    const gss_buffer_t password,
Packit Service 99d1c0
    OM_uint32 time_req,
Packit Service 99d1c0
    const gss_OID_set desired_mechs,
Packit Service 99d1c0
    int cred_usage,
Packit Service 99d1c0
    gss_cred_id_t *output_cred_handle,
Packit Service 99d1c0
    gss_OID_set *actual_mechs,
Packit Service 99d1c0
    OM_uint32 *time_rec)
Packit Service 99d1c0
{
Packit Service 99d1c0
Packit Service 99d1c0
    /* Initialize outputs. */
Packit Service 99d1c0
Packit Service 99d1c0
    if (minor_status != NULL)
Packit Service 99d1c0
	*minor_status = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    if (output_cred_handle != NULL)
Packit Service 99d1c0
	*output_cred_handle = GSS_C_NO_CREDENTIAL;
Packit Service 99d1c0
Packit Service 99d1c0
    if (actual_mechs != NULL)
Packit Service 99d1c0
	*actual_mechs = GSS_C_NULL_OID_SET;
Packit Service 99d1c0
Packit Service 99d1c0
    if (time_rec != NULL)
Packit Service 99d1c0
	*time_rec = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    /* Validate arguments. */
Packit Service 99d1c0
Packit Service 99d1c0
    if (desired_name == GSS_C_NO_NAME)
Packit Service 99d1c0
	return (GSS_S_BAD_NAME);
Packit Service 99d1c0
Packit Service 99d1c0
    if (minor_status == NULL)
Packit Service 99d1c0
	return (GSS_S_CALL_INACCESSIBLE_WRITE);
Packit Service 99d1c0
Packit Service 99d1c0
    if (output_cred_handle == NULL)
Packit Service 99d1c0
	return (GSS_S_CALL_INACCESSIBLE_WRITE);
Packit Service 99d1c0
Packit Service 99d1c0
    if (cred_usage != GSS_C_ACCEPT
Packit Service 99d1c0
	&& cred_usage != GSS_C_INITIATE
Packit Service 99d1c0
	&& cred_usage != GSS_C_BOTH) {
Packit Service 99d1c0
	if (minor_status) {
Packit Service 99d1c0
	    *minor_status = EINVAL;
Packit Service 99d1c0
	    map_errcode(minor_status);
Packit Service 99d1c0
	}
Packit Service 99d1c0
	return GSS_S_FAILURE;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (password == GSS_C_NO_BUFFER ||
Packit Service 99d1c0
        password->length == 0 ||
Packit Service 99d1c0
        password->value == NULL) {
Packit Service 99d1c0
	if (minor_status) {
Packit Service 99d1c0
	    *minor_status = EINVAL;
Packit Service 99d1c0
	    map_errcode(minor_status);
Packit Service 99d1c0
	}
Packit Service 99d1c0
	return GSS_S_FAILURE;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    return (GSS_S_COMPLETE);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
Packit Service 99d1c0
OM_uint32 KRB5_CALLCONV
Packit Service 99d1c0
gss_acquire_cred_with_password(
Packit Service 99d1c0
    minor_status,
Packit Service 99d1c0
    desired_name,
Packit Service 99d1c0
    password,
Packit Service 99d1c0
    time_req,
Packit Service 99d1c0
    desired_mechs,
Packit Service 99d1c0
    cred_usage,
Packit Service 99d1c0
    output_cred_handle,
Packit Service 99d1c0
    actual_mechs,
Packit Service 99d1c0
    time_rec)
Packit Service 99d1c0
Packit Service 99d1c0
OM_uint32 *		minor_status;
Packit Service 99d1c0
const gss_name_t	desired_name;
Packit Service 99d1c0
const gss_buffer_t	password;
Packit Service 99d1c0
OM_uint32		time_req;
Packit Service 99d1c0
const gss_OID_set	desired_mechs;
Packit Service 99d1c0
int			cred_usage;
Packit Service 99d1c0
gss_cred_id_t *		output_cred_handle;
Packit Service 99d1c0
gss_OID_set *		actual_mechs;
Packit Service 99d1c0
OM_uint32 *		time_rec;
Packit Service 99d1c0
{
Packit Service 99d1c0
    OM_uint32 major = GSS_S_FAILURE;
Packit Service 99d1c0
    OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
Packit Service 99d1c0
    gss_OID_set_desc default_OID_set;
Packit Service 99d1c0
    gss_OID_set mechs;
Packit Service 99d1c0
    gss_OID_desc default_OID;
Packit Service 99d1c0
    gss_mechanism mech;
Packit Service 99d1c0
    unsigned int i;
Packit Service 99d1c0
    gss_union_cred_t creds;
Packit Service 99d1c0
Packit Service 99d1c0
    major = val_acq_cred_pw_args(minor_status,
Packit Service 99d1c0
			         desired_name,
Packit Service 99d1c0
			         password,
Packit Service 99d1c0
			         time_req,
Packit Service 99d1c0
			         desired_mechs,
Packit Service 99d1c0
			         cred_usage,
Packit Service 99d1c0
			         output_cred_handle,
Packit Service 99d1c0
			         actual_mechs,
Packit Service 99d1c0
			         time_rec);
Packit Service 99d1c0
    if (major != GSS_S_COMPLETE)
Packit Service 99d1c0
	return (major);
Packit Service 99d1c0
Packit Service 99d1c0
    /* Initial value needed below. */
Packit Service 99d1c0
    major = GSS_S_FAILURE;
Packit Service 99d1c0
Packit Service 99d1c0
    /*
Packit Service 99d1c0
     * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
Packit Service 99d1c0
     * appropriate default.  We use the first mechanism in the
Packit Service 99d1c0
     * mechansim list as the default. This set is created with
Packit Service 99d1c0
     * statics thus needs not be freed
Packit Service 99d1c0
     */
Packit Service 99d1c0
    if(desired_mechs == GSS_C_NULL_OID_SET) {
Packit Service 99d1c0
	mech = gssint_get_mechanism(NULL);
Packit Service 99d1c0
	if (mech == NULL)
Packit Service 99d1c0
	    return (GSS_S_BAD_MECH);
Packit Service 99d1c0
Packit Service 99d1c0
	mechs = &default_OID_set;
Packit Service 99d1c0
	default_OID_set.count = 1;
Packit Service 99d1c0
	default_OID_set.elements = &default_OID;
Packit Service 99d1c0
	default_OID.length = mech->mech_type.length;
Packit Service 99d1c0
	default_OID.elements = mech->mech_type.elements;
Packit Service 99d1c0
    } else
Packit Service 99d1c0
	mechs = desired_mechs;
Packit Service 99d1c0
Packit Service 99d1c0
    if (mechs->count == 0)
Packit Service 99d1c0
	return (GSS_S_BAD_MECH);
Packit Service 99d1c0
Packit Service 99d1c0
    /* allocate the output credential structure */
Packit Service 99d1c0
    creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
Packit Service 99d1c0
    if (creds == NULL)
Packit Service 99d1c0
	return (GSS_S_FAILURE);
Packit Service 99d1c0
Packit Service 99d1c0
    /* initialize to 0s */
Packit Service 99d1c0
    (void) memset(creds, 0, sizeof (gss_union_cred_desc));
Packit Service 99d1c0
    creds->loopback = creds;
Packit Service 99d1c0
Packit Service 99d1c0
    /* for each requested mech attempt to obtain a credential */
Packit Service 99d1c0
    for (i = 0; i < mechs->count; i++) {
Packit Service 99d1c0
	major = gss_add_cred_with_password(minor_status, (gss_cred_id_t)creds,
Packit Service 99d1c0
			     desired_name,
Packit Service 99d1c0
			     &mechs->elements[i],
Packit Service 99d1c0
			     password,
Packit Service 99d1c0
			     cred_usage, time_req, time_req, NULL,
Packit Service 99d1c0
			     NULL, &initTimeOut, &acceptTimeOut);
Packit Service 99d1c0
	if (major == GSS_S_COMPLETE) {
Packit Service 99d1c0
	    /* update the credential's time */
Packit Service 99d1c0
	    if (cred_usage == GSS_C_ACCEPT) {
Packit Service 99d1c0
		if (outTime > acceptTimeOut)
Packit Service 99d1c0
		    outTime = acceptTimeOut;
Packit Service 99d1c0
	    } else if (cred_usage == GSS_C_INITIATE) {
Packit Service 99d1c0
		if (outTime > initTimeOut)
Packit Service 99d1c0
		    outTime = initTimeOut;
Packit Service 99d1c0
	    } else {
Packit Service 99d1c0
		/*
Packit Service 99d1c0
		 * time_rec is the lesser of the
Packit Service 99d1c0
		 * init/accept times
Packit Service 99d1c0
		 */
Packit Service 99d1c0
		if (initTimeOut > acceptTimeOut)
Packit Service 99d1c0
		    outTime = (outTime > acceptTimeOut) ?
Packit Service 99d1c0
			acceptTimeOut : outTime;
Packit Service 99d1c0
		else
Packit Service 99d1c0
		    outTime = (outTime > initTimeOut) ?
Packit Service 99d1c0
			initTimeOut : outTime;
Packit Service 99d1c0
	    }
Packit Service 99d1c0
	}
Packit Service 99d1c0
    } /* for */
Packit Service 99d1c0
Packit Service 99d1c0
    /* ensure that we have at least one credential element */
Packit Service 99d1c0
    if (creds->count < 1) {
Packit Service 99d1c0
	free(creds);
Packit Service 99d1c0
	return (major);
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    /*
Packit Service 99d1c0
     * fill in output parameters
Packit Service 99d1c0
     * setup the actual mechs output parameter
Packit Service 99d1c0
     */
Packit Service 99d1c0
    if (actual_mechs != NULL) {
Packit Service 99d1c0
	major = gssint_make_public_oid_set(minor_status, creds->mechs_array,
Packit Service 99d1c0
					   creds->count, actual_mechs);
Packit Service 99d1c0
	if (GSS_ERROR(major)) {
Packit Service 99d1c0
	    (void) gss_release_cred(minor_status,
Packit Service 99d1c0
				    (gss_cred_id_t *)&creds);
Packit Service 99d1c0
	    return (major);
Packit Service 99d1c0
	}
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (time_rec)
Packit Service 99d1c0
	*time_rec = outTime;
Packit Service 99d1c0
Packit Service 99d1c0
Packit Service 99d1c0
    creds->loopback = creds;
Packit Service 99d1c0
    *output_cred_handle = (gss_cred_id_t)creds;
Packit Service 99d1c0
    return (GSS_S_COMPLETE);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
static OM_uint32
Packit Service 99d1c0
val_add_cred_pw_args(
Packit Service 99d1c0
    OM_uint32 *minor_status,
Packit Service 99d1c0
    gss_cred_id_t input_cred_handle,
Packit Service 99d1c0
    const gss_name_t desired_name,
Packit Service 99d1c0
    const gss_OID desired_mech,
Packit Service 99d1c0
    const gss_buffer_t password,
Packit Service 99d1c0
    gss_cred_usage_t cred_usage,
Packit Service 99d1c0
    OM_uint32 initiator_time_req,
Packit Service 99d1c0
    OM_uint32 acceptor_time_req,
Packit Service 99d1c0
    gss_cred_id_t *output_cred_handle,
Packit Service 99d1c0
    gss_OID_set *actual_mechs,
Packit Service 99d1c0
    OM_uint32 *initiator_time_rec,
Packit Service 99d1c0
    OM_uint32 *acceptor_time_rec)
Packit Service 99d1c0
{
Packit Service 99d1c0
Packit Service 99d1c0
    /* Initialize outputs. */
Packit Service 99d1c0
Packit Service 99d1c0
    if (minor_status != NULL)
Packit Service 99d1c0
	*minor_status = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    if (output_cred_handle != NULL)
Packit Service 99d1c0
	*output_cred_handle = GSS_C_NO_CREDENTIAL;
Packit Service 99d1c0
Packit Service 99d1c0
    if (actual_mechs != NULL)
Packit Service 99d1c0
	*actual_mechs = GSS_C_NO_OID_SET;
Packit Service 99d1c0
Packit Service 99d1c0
    if (acceptor_time_rec != NULL)
Packit Service 99d1c0
	*acceptor_time_rec = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    if (initiator_time_rec != NULL)
Packit Service 99d1c0
	*initiator_time_rec = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    /* Validate arguments. */
Packit Service 99d1c0
Packit Service 99d1c0
    if (desired_name == GSS_C_NO_NAME)
Packit Service 99d1c0
	return (GSS_S_BAD_NAME);
Packit Service 99d1c0
Packit Service 99d1c0
    if (minor_status == NULL)
Packit Service 99d1c0
	return (GSS_S_CALL_INACCESSIBLE_WRITE);
Packit Service 99d1c0
Packit Service 99d1c0
    if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
Packit Service 99d1c0
	output_cred_handle == NULL)
Packit Service 99d1c0
	return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
Packit Service 99d1c0
Packit Service 99d1c0
    if (cred_usage != GSS_C_ACCEPT
Packit Service 99d1c0
	&& cred_usage != GSS_C_INITIATE
Packit Service 99d1c0
	&& cred_usage != GSS_C_BOTH) {
Packit Service 99d1c0
	if (minor_status) {
Packit Service 99d1c0
	    *minor_status = EINVAL;
Packit Service 99d1c0
	    map_errcode(minor_status);
Packit Service 99d1c0
	}
Packit Service 99d1c0
	return GSS_S_FAILURE;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (password == GSS_C_NO_BUFFER ||
Packit Service 99d1c0
        password->length == 0 ||
Packit Service 99d1c0
        password->value == NULL) {
Packit Service 99d1c0
	if (minor_status) {
Packit Service 99d1c0
	    *minor_status = EINVAL;
Packit Service 99d1c0
	    map_errcode(minor_status);
Packit Service 99d1c0
	}
Packit Service 99d1c0
	return GSS_S_FAILURE;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
Packit Service 99d1c0
    return (GSS_S_COMPLETE);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
Packit Service 99d1c0
/* V2 KRB5_CALLCONV */
Packit Service 99d1c0
OM_uint32 KRB5_CALLCONV
Packit Service 99d1c0
gss_add_cred_with_password(minor_status, input_cred_handle,
Packit Service 99d1c0
		  desired_name, desired_mech, password, cred_usage,
Packit Service 99d1c0
		  initiator_time_req, acceptor_time_req,
Packit Service 99d1c0
		  output_cred_handle, actual_mechs,
Packit Service 99d1c0
		  initiator_time_rec, acceptor_time_rec)
Packit Service 99d1c0
    OM_uint32		*minor_status;
Packit Service 99d1c0
    const gss_cred_id_t	input_cred_handle;
Packit Service 99d1c0
    const gss_name_t	desired_name;
Packit Service 99d1c0
    const gss_OID	desired_mech;
Packit Service 99d1c0
    const gss_buffer_t	password;
Packit Service 99d1c0
    gss_cred_usage_t	cred_usage;
Packit Service 99d1c0
    OM_uint32		initiator_time_req;
Packit Service 99d1c0
    OM_uint32		acceptor_time_req;
Packit Service 99d1c0
    gss_cred_id_t	*output_cred_handle;
Packit Service 99d1c0
    gss_OID_set		*actual_mechs;
Packit Service 99d1c0
    OM_uint32		*initiator_time_rec;
Packit Service 99d1c0
    OM_uint32		*acceptor_time_rec;
Packit Service 99d1c0
{
Packit Service 99d1c0
    OM_uint32		status, temp_minor_status;
Packit Service 99d1c0
    OM_uint32		time_req, time_rec;
Packit Service 99d1c0
    gss_union_name_t	union_name;
Packit Service 99d1c0
    gss_union_cred_t	new_union_cred, union_cred;
Packit Service 99d1c0
    gss_name_t		internal_name = GSS_C_NO_NAME;
Packit Service 99d1c0
    gss_name_t		allocated_name = GSS_C_NO_NAME;
Packit Service 99d1c0
    gss_mechanism       mech;
Packit Service 99d1c0
    gss_cred_id_t	cred = NULL;
Packit Service 99d1c0
    gss_OID		new_mechs_array = NULL;
Packit Service 99d1c0
    gss_cred_id_t *	new_cred_array = NULL;
Packit Service 99d1c0
    gss_OID_set		target_mechs = GSS_C_NO_OID_SET;
Packit Service 99d1c0
    gss_OID		selected_mech = GSS_C_NO_OID;
Packit Service 99d1c0
Packit Service 99d1c0
    status = val_add_cred_pw_args(minor_status,
Packit Service 99d1c0
			          input_cred_handle,
Packit Service 99d1c0
			          desired_name,
Packit Service 99d1c0
			          desired_mech,
Packit Service 99d1c0
			          password,
Packit Service 99d1c0
			          cred_usage,
Packit Service 99d1c0
			          initiator_time_req,
Packit Service 99d1c0
			          acceptor_time_req,
Packit Service 99d1c0
			          output_cred_handle,
Packit Service 99d1c0
			          actual_mechs,
Packit Service 99d1c0
			          initiator_time_rec,
Packit Service 99d1c0
			          acceptor_time_rec);
Packit Service 99d1c0
    if (status != GSS_S_COMPLETE)
Packit Service 99d1c0
	return (status);
Packit Service 99d1c0
Packit Service 99d1c0
    status = gssint_select_mech_type(minor_status, desired_mech,
Packit Service 99d1c0
				     &selected_mech);
Packit Service 99d1c0
    if (status != GSS_S_COMPLETE)
Packit Service 99d1c0
	return (status);
Packit Service 99d1c0
Packit Service 99d1c0
    mech = gssint_get_mechanism(selected_mech);
Packit Service 99d1c0
    if (!mech)
Packit Service 99d1c0
	return GSS_S_BAD_MECH;
Packit Service 99d1c0
    if (!mech->gssspi_acquire_cred_with_password)
Packit Service 99d1c0
	return GSS_S_UNAVAILABLE;
Packit Service 99d1c0
Packit Service 99d1c0
    if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
Packit Service 99d1c0
	union_cred = malloc(sizeof (gss_union_cred_desc));
Packit Service 99d1c0
	if (union_cred == NULL)
Packit Service 99d1c0
	    return (GSS_S_FAILURE);
Packit Service 99d1c0
Packit Service 99d1c0
	(void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
Packit Service 99d1c0
Packit Service 99d1c0
	/* for default credentials we will use GSS_C_NO_NAME */
Packit Service 99d1c0
	internal_name = GSS_C_NO_NAME;
Packit Service 99d1c0
    } else {
Packit Service 99d1c0
	union_cred = (gss_union_cred_t)input_cred_handle;
Packit Service 99d1c0
	if (gssint_get_mechanism_cred(union_cred, selected_mech) !=
Packit Service 99d1c0
	    GSS_C_NO_CREDENTIAL)
Packit Service 99d1c0
	    return (GSS_S_DUPLICATE_ELEMENT);
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    /* may need to create a mechanism specific name */
Packit Service 99d1c0
    union_name = (gss_union_name_t)desired_name;
Packit Service 99d1c0
    if (union_name->mech_type &&
Packit Service 99d1c0
	g_OID_equal(union_name->mech_type, selected_mech))
Packit Service 99d1c0
	internal_name = union_name->mech_name;
Packit Service 99d1c0
    else {
Packit Service 99d1c0
	if (gssint_import_internal_name(minor_status,
Packit Service 99d1c0
					selected_mech, union_name,
Packit Service 99d1c0
					&allocated_name) != GSS_S_COMPLETE)
Packit Service 99d1c0
	    return (GSS_S_BAD_NAME);
Packit Service 99d1c0
	internal_name = allocated_name;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (cred_usage == GSS_C_ACCEPT)
Packit Service 99d1c0
	time_req = acceptor_time_req;
Packit Service 99d1c0
    else if (cred_usage == GSS_C_INITIATE)
Packit Service 99d1c0
	time_req = initiator_time_req;
Packit Service 99d1c0
    else if (cred_usage == GSS_C_BOTH)
Packit Service 99d1c0
	time_req = (acceptor_time_req > initiator_time_req) ?
Packit Service 99d1c0
	    acceptor_time_req : initiator_time_req;
Packit Service 99d1c0
    else
Packit Service 99d1c0
	time_req = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    status = gss_create_empty_oid_set(minor_status, &target_mechs);
Packit Service 99d1c0
    if (status != GSS_S_COMPLETE)
Packit Service 99d1c0
	goto errout;
Packit Service 99d1c0
Packit Service 99d1c0
    status = gss_add_oid_set_member(minor_status,
Packit Service 99d1c0
				    gssint_get_public_oid(selected_mech),
Packit Service 99d1c0
				    &target_mechs);
Packit Service 99d1c0
    if (status != GSS_S_COMPLETE)
Packit Service 99d1c0
	goto errout;
Packit Service 99d1c0
Packit Service 99d1c0
    status = mech->gssspi_acquire_cred_with_password(minor_status,
Packit Service 99d1c0
						     internal_name,
Packit Service 99d1c0
						     password,
Packit Service 99d1c0
						     time_req,
Packit Service 99d1c0
						     target_mechs,
Packit Service 99d1c0
						     cred_usage,
Packit Service 99d1c0
						     &cred,
Packit Service 99d1c0
						     NULL,
Packit Service 99d1c0
						     &time_rec);
Packit Service 99d1c0
    if (status != GSS_S_COMPLETE) {
Packit Service 99d1c0
	map_error(minor_status, mech);
Packit Service 99d1c0
	goto errout;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    /* now add the new credential elements */
Packit Service 99d1c0
    new_mechs_array = (gss_OID)
Packit Service 99d1c0
	malloc(sizeof (gss_OID_desc) * (union_cred->count+1));
Packit Service 99d1c0
Packit Service 99d1c0
    new_cred_array = (gss_cred_id_t *)
Packit Service 99d1c0
	malloc(sizeof (gss_cred_id_t) * (union_cred->count+1));
Packit Service 99d1c0
Packit Service 99d1c0
    if (!new_mechs_array || !new_cred_array) {
Packit Service 99d1c0
	status = GSS_S_FAILURE;
Packit Service 99d1c0
	goto errout;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (acceptor_time_rec)
Packit Service 99d1c0
	if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
Packit Service 99d1c0
	    *acceptor_time_rec = time_rec;
Packit Service 99d1c0
    if (initiator_time_rec)
Packit Service 99d1c0
	if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
Packit Service 99d1c0
	    *initiator_time_rec = time_rec;
Packit Service 99d1c0
Packit Service 99d1c0
    /*
Packit Service 99d1c0
     * OK, expand the mechanism array and the credential array
Packit Service 99d1c0
     */
Packit Service 99d1c0
    (void) memcpy(new_mechs_array, union_cred->mechs_array,
Packit Service 99d1c0
		  sizeof (gss_OID_desc) * union_cred->count);
Packit Service 99d1c0
    (void) memcpy(new_cred_array, union_cred->cred_array,
Packit Service 99d1c0
		  sizeof (gss_cred_id_t) * union_cred->count);
Packit Service 99d1c0
Packit Service 99d1c0
    new_cred_array[union_cred->count] = cred;
Packit Service 99d1c0
    if ((new_mechs_array[union_cred->count].elements =
Packit Service 99d1c0
	 malloc(selected_mech->length)) == NULL)
Packit Service 99d1c0
	goto errout;
Packit Service 99d1c0
Packit Service 99d1c0
    g_OID_copy(&new_mechs_array[union_cred->count], selected_mech);
Packit Service 99d1c0
Packit Service 99d1c0
    if (actual_mechs != NULL) {
Packit Service 99d1c0
	status = gssint_make_public_oid_set(minor_status, new_mechs_array,
Packit Service 99d1c0
					    union_cred->count + 1,
Packit Service 99d1c0
					    actual_mechs);
Packit Service 99d1c0
	if (GSS_ERROR(status)) {
Packit Service 99d1c0
	    free(new_mechs_array[union_cred->count].elements);
Packit Service 99d1c0
	    goto errout;
Packit Service 99d1c0
	}
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (output_cred_handle == NULL) {
Packit Service 99d1c0
	free(union_cred->mechs_array);
Packit Service 99d1c0
	free(union_cred->cred_array);
Packit Service 99d1c0
	new_union_cred = union_cred;
Packit Service 99d1c0
    } else {
Packit Service 99d1c0
	new_union_cred = malloc(sizeof (gss_union_cred_desc));
Packit Service 99d1c0
	if (new_union_cred == NULL) {
Packit Service 99d1c0
	    free(new_mechs_array[union_cred->count].elements);
Packit Service 99d1c0
	    goto errout;
Packit Service 99d1c0
	}
Packit Service 99d1c0
	*new_union_cred = *union_cred;
Packit Service 99d1c0
	*output_cred_handle = (gss_cred_id_t)new_union_cred;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    new_union_cred->mechs_array = new_mechs_array;
Packit Service 99d1c0
    new_union_cred->cred_array = new_cred_array;
Packit Service 99d1c0
    new_union_cred->count++;
Packit Service 99d1c0
    new_union_cred->loopback = new_union_cred;
Packit Service 99d1c0
Packit Service 99d1c0
    /* We're done with the internal name. Free it if we allocated it. */
Packit Service 99d1c0
Packit Service 99d1c0
    if (allocated_name)
Packit Service 99d1c0
	(void) gssint_release_internal_name(&temp_minor_status,
Packit Service 99d1c0
					    selected_mech,
Packit Service 99d1c0
					   &allocated_name);
Packit Service 99d1c0
Packit Service 99d1c0
    if (target_mechs)
Packit Service 99d1c0
	(void)gss_release_oid_set(&temp_minor_status, &target_mechs);
Packit Service 99d1c0
Packit Service 99d1c0
    return (GSS_S_COMPLETE);
Packit Service 99d1c0
Packit Service 99d1c0
errout:
Packit Service 99d1c0
    if (new_mechs_array)
Packit Service 99d1c0
	free(new_mechs_array);
Packit Service 99d1c0
    if (new_cred_array)
Packit Service 99d1c0
	free(new_cred_array);
Packit Service 99d1c0
Packit Service 99d1c0
    if (cred != NULL && mech->gss_release_cred)
Packit Service 99d1c0
	mech->gss_release_cred(&temp_minor_status, &cred);
Packit Service 99d1c0
Packit Service 99d1c0
    if (allocated_name)
Packit Service 99d1c0
	(void) gssint_release_internal_name(&temp_minor_status,
Packit Service 99d1c0
					    selected_mech, &allocated_name);
Packit Service 99d1c0
Packit Service 99d1c0
    if (target_mechs)
Packit Service 99d1c0
	(void)gss_release_oid_set(&temp_minor_status, &target_mechs);
Packit Service 99d1c0
Packit Service 99d1c0
    if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred)
Packit Service 99d1c0
	free(union_cred);
Packit Service 99d1c0
Packit Service 99d1c0
    return (status);
Packit Service 99d1c0
}