gss_acquire_cred.c revision 272461
124424Swosch/*-
224424Swosch * Copyright (c) 2005 Doug Rabson
324424Swosch * All rights reserved.
424424Swosch *
524424Swosch * Redistribution and use in source and binary forms, with or without
624424Swosch * modification, are permitted provided that the following conditions
724424Swosch * are met:
824424Swosch * 1. Redistributions of source code must retain the above copyright
924424Swosch *    notice, this list of conditions and the following disclaimer.
1024424Swosch * 2. Redistributions in binary form must reproduce the above copyright
1124424Swosch *    notice, this list of conditions and the following disclaimer in the
1224424Swosch *    documentation and/or other materials provided with the distribution.
1324424Swosch *
1424424Swosch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1542704Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1642704Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1742704Swosch * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1824424Swosch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1942704Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2042704Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2142704Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2242704Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2342704Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2442704Swosch * SUCH DAMAGE.
2542704Swosch *
2642704Swosch *	$FreeBSD: releng/10.1/lib/libgssapi/gss_acquire_cred.c 178828 2008-05-07 13:53:12Z dfr $
2742704Swosch */
2842704Swosch
2942704Swosch#include <gssapi/gssapi.h>
3042704Swosch#include <stdlib.h>
3142704Swosch#include <errno.h>
3242704Swosch
3324424Swosch#include "mech_switch.h"
3425031Swosch#include "name.h"
3525031Swosch#include "cred.h"
3635961Swosch
3724424SwoschOM_uint32
3824424Swoschgss_acquire_cred(OM_uint32 *minor_status,
3924424Swosch    const gss_name_t desired_name,
4025031Swosch    OM_uint32 time_req,
4125031Swosch    const gss_OID_set desired_mechs,
4242704Swosch    gss_cred_usage_t cred_usage,
4324424Swosch    gss_cred_id_t *output_cred_handle,
4442704Swosch    gss_OID_set *actual_mechs,
4524424Swosch    OM_uint32 *time_rec)
4642704Swosch{
4724424Swosch	OM_uint32 major_status;
4824424Swosch	gss_OID_set mechs = desired_mechs;
4924424Swosch	gss_OID_set_desc set;
5042704Swosch	struct _gss_name *name = (struct _gss_name *) desired_name;
5125031Swosch	struct _gss_mech_switch *m;
5225031Swosch	struct _gss_cred *cred;
5325031Swosch	struct _gss_mechanism_cred *mc;
5425031Swosch	struct _gss_mechanism_name *mn;
5524424Swosch	OM_uint32 min_time, cred_time;
5624424Swosch	size_t i;
5724424Swosch
5824424Swosch	*minor_status = 0;
5924424Swosch	if (output_cred_handle)
6024424Swosch		*output_cred_handle = GSS_C_NO_CREDENTIAL;
6124424Swosch	if (actual_mechs)
6225031Swosch		*actual_mechs = GSS_C_NO_OID_SET;
6324424Swosch	if (time_rec)
6424424Swosch		*time_rec = 0;
6525031Swosch
6625031Swosch	_gss_load_mech();
6745349Swosch
6825031Swosch	/*
6945349Swosch	 * First make sure that at least one of the requested
7045349Swosch	 * mechanisms is one that we support.
7145349Swosch	 */
7245349Swosch	if (mechs) {
7345349Swosch		for (i = 0; i < mechs->count; i++) {
7445349Swosch			int t;
7545349Swosch			gss_test_oid_set_member(minor_status,
7645349Swosch			    &mechs->elements[i], _gss_mech_oids, &t);
7745349Swosch			if (t)
7845349Swosch				break;
7945349Swosch		}
8045349Swosch		if (i == mechs->count) {
8145349Swosch			*minor_status = 0;
8245349Swosch			return (GSS_S_BAD_MECH);
8346318Swosch		}
8445349Swosch	} else {
8545349Swosch		mechs = _gss_mech_oids;
8645349Swosch	}
8746318Swosch
8846318Swosch	if (actual_mechs) {
8946318Swosch		major_status = gss_create_empty_oid_set(minor_status,
9046318Swosch		    actual_mechs);
9146318Swosch		if (major_status)
9246318Swosch			return (major_status);
9346318Swosch	}
9445349Swosch
9545349Swosch	cred = malloc(sizeof(struct _gss_cred));
9645349Swosch	if (!cred) {
9746318Swosch		if (actual_mechs)
9846318Swosch			gss_release_oid_set(minor_status, actual_mechs);
9946318Swosch		*minor_status = ENOMEM;
10046318Swosch		return (GSS_S_FAILURE);
10146318Swosch	}
10246318Swosch	SLIST_INIT(&cred->gc_mc);
10346318Swosch
10446318Swosch	set.count = 1;
10546318Swosch	min_time = GSS_C_INDEFINITE;
10646318Swosch	for (i = 0; i < mechs->count; i++) {
10746318Swosch		m = _gss_find_mech_switch(&mechs->elements[i]);
10846318Swosch		if (!m)
10946318Swosch			continue;
11046318Swosch
11146318Swosch		if (desired_name != GSS_C_NO_NAME) {
11246318Swosch			major_status = _gss_find_mn(minor_status, name,
11346318Swosch						    &mechs->elements[i], &mn);
11446318Swosch			if (major_status != GSS_S_COMPLETE)
11546318Swosch				continue;
11646318Swosch		}
11746318Swosch
11846318Swosch		mc = malloc(sizeof(struct _gss_mechanism_cred));
11946318Swosch		if (!mc) {
12046318Swosch			continue;
12146318Swosch		}
12246318Swosch		mc->gmc_mech = m;
12346318Swosch		mc->gmc_mech_oid = &m->gm_mech_oid;
12424424Swosch
12524424Swosch		/*
12624424Swosch		 * XXX Probably need to do something with actual_mechs.
12724424Swosch		 */
12824424Swosch		set.elements = &mechs->elements[i];
12925031Swosch		major_status = m->gm_acquire_cred(minor_status,
13025031Swosch		    (desired_name != GSS_C_NO_NAME
13124424Swosch			? mn->gmn_name : GSS_C_NO_NAME),
13225031Swosch		    time_req, &set, cred_usage,
13325031Swosch		    &mc->gmc_cred, NULL, &cred_time);
13425031Swosch		if (major_status) {
13525031Swosch			free(mc);
13625031Swosch			continue;
13725031Swosch		}
13825031Swosch		if (cred_time < min_time)
13925031Swosch			min_time = cred_time;
14025031Swosch
14125031Swosch		if (actual_mechs) {
14225031Swosch			major_status = gss_add_oid_set_member(minor_status,
14325031Swosch			    mc->gmc_mech_oid, actual_mechs);
14425031Swosch			if (major_status) {
14525031Swosch				m->gm_release_cred(minor_status,
14625031Swosch				    &mc->gmc_cred);
14738440Sjkh				free(mc);
14845349Swosch				continue;
14945349Swosch			}
15042704Swosch		}
15125031Swosch
15225031Swosch		SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
15324424Swosch	}
15425031Swosch
15525031Swosch	/*
15625031Swosch	 * If we didn't manage to create a single credential, return
15725031Swosch	 * an error.
15825031Swosch	 */
15925031Swosch	if (!SLIST_FIRST(&cred->gc_mc)) {
16025031Swosch		free(cred);
16125031Swosch		if (actual_mechs)
16225031Swosch			gss_release_oid_set(minor_status, actual_mechs);
16325031Swosch		*minor_status = 0;
16424424Swosch		return (GSS_S_NO_CRED);
16525031Swosch	}
16625031Swosch
16725031Swosch	if (time_rec)
16825031Swosch		*time_rec = min_time;
16925031Swosch	*output_cred_handle = (gss_cred_id_t) cred;
17025031Swosch	*minor_status = 0;
17125031Swosch	return (GSS_S_COMPLETE);
17242704Swosch}
17342704Swosch