1178828Sdfr/*
2178828Sdfr * Copyright (c) 2004, PADL Software Pty Ltd.
3178828Sdfr * All rights reserved.
4178828Sdfr *
5178828Sdfr * Redistribution and use in source and binary forms, with or without
6178828Sdfr * modification, are permitted provided that the following conditions
7178828Sdfr * are met:
8178828Sdfr *
9178828Sdfr * 1. Redistributions of source code must retain the above copyright
10178828Sdfr *    notice, this list of conditions and the following disclaimer.
11178828Sdfr *
12178828Sdfr * 2. Redistributions in binary form must reproduce the above copyright
13178828Sdfr *    notice, this list of conditions and the following disclaimer in the
14178828Sdfr *    documentation and/or other materials provided with the distribution.
15178828Sdfr *
16178828Sdfr * 3. Neither the name of PADL Software nor the names of its contributors
17178828Sdfr *    may be used to endorse or promote products derived from this software
18178828Sdfr *    without specific prior written permission.
19178828Sdfr *
20178828Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21178828Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23178828Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24178828Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25178828Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28178828Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29178828Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30178828Sdfr * SUCH DAMAGE.
31178828Sdfr */
32178828Sdfr/* $FreeBSD$ */
33178828Sdfr/* RCSID("$Id: gss_set_cred_option.c 21126 2007-06-18 20:19:59Z lha $"); */
34178828Sdfr
35178828Sdfr#include <gssapi/gssapi.h>
36178828Sdfr#include <stdlib.h>
37178828Sdfr#include <errno.h>
38178828Sdfr
39178828Sdfr#include "mech_switch.h"
40178828Sdfr#include "cred.h"
41178828Sdfr
42178828SdfrOM_uint32
43178828Sdfrgss_set_cred_option (OM_uint32 *minor_status,
44178828Sdfr		     gss_cred_id_t *cred_handle,
45178828Sdfr		     const gss_OID object,
46178828Sdfr		     const gss_buffer_t value)
47178828Sdfr{
48178828Sdfr	struct _gss_cred *cred = (struct _gss_cred *) *cred_handle;
49178828Sdfr	OM_uint32	major_status = GSS_S_COMPLETE;
50178828Sdfr	struct _gss_mechanism_cred *mc;
51178828Sdfr	int one_ok = 0;
52178828Sdfr
53178828Sdfr	*minor_status = 0;
54178828Sdfr
55178828Sdfr	_gss_load_mech();
56178828Sdfr
57178828Sdfr	if (cred == NULL) {
58178828Sdfr		struct _gss_mech_switch *m;
59178828Sdfr
60178828Sdfr		cred = malloc(sizeof(*cred));
61178828Sdfr		if (cred == NULL)
62178828Sdfr		    return GSS_S_FAILURE;
63178828Sdfr
64178828Sdfr		SLIST_INIT(&cred->gc_mc);
65178828Sdfr
66178828Sdfr		SLIST_FOREACH(m, &_gss_mechs, gm_link) {
67178828Sdfr
68178828Sdfr			if (m->gm_set_cred_option == NULL)
69178828Sdfr				continue;
70178828Sdfr
71178828Sdfr			mc = malloc(sizeof(*mc));
72178828Sdfr			if (mc == NULL) {
73178828Sdfr			    *cred_handle = (gss_cred_id_t)cred;
74178828Sdfr			    gss_release_cred(minor_status, cred_handle);
75178828Sdfr			    *minor_status = ENOMEM;
76178828Sdfr			    return GSS_S_FAILURE;
77178828Sdfr			}
78178828Sdfr
79178828Sdfr			mc->gmc_mech = m;
80178828Sdfr			mc->gmc_mech_oid = &m->gm_mech_oid;
81178828Sdfr			mc->gmc_cred = GSS_C_NO_CREDENTIAL;
82178828Sdfr
83178828Sdfr			major_status = m->gm_set_cred_option(
84178828Sdfr			    minor_status, &mc->gmc_cred, object, value);
85178828Sdfr
86178828Sdfr			if (major_status) {
87178828Sdfr				free(mc);
88178828Sdfr				continue;
89178828Sdfr			}
90178828Sdfr			one_ok = 1;
91178828Sdfr			SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
92178828Sdfr		}
93178828Sdfr		*cred_handle = (gss_cred_id_t)cred;
94178828Sdfr		if (!one_ok) {
95178828Sdfr			OM_uint32 junk;
96178828Sdfr			gss_release_cred(&junk, cred_handle);
97178828Sdfr		}
98178828Sdfr	} else {
99178828Sdfr		struct _gss_mech_switch *m;
100178828Sdfr
101178828Sdfr		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
102178828Sdfr			m = mc->gmc_mech;
103178828Sdfr
104178828Sdfr			if (m == NULL)
105178828Sdfr				return GSS_S_BAD_MECH;
106178828Sdfr
107178828Sdfr			if (m->gm_set_cred_option == NULL)
108178828Sdfr				continue;
109178828Sdfr
110178828Sdfr			major_status = m->gm_set_cred_option(minor_status,
111178828Sdfr			    &mc->gmc_cred, object, value);
112178828Sdfr			if (major_status == GSS_S_COMPLETE)
113178828Sdfr				one_ok = 1;
114178828Sdfr			else
115178828Sdfr				_gss_mg_error(m, major_status, *minor_status);
116178828Sdfr
117178828Sdfr		}
118178828Sdfr	}
119178828Sdfr	if (one_ok) {
120178828Sdfr		*minor_status = 0;
121178828Sdfr		return (GSS_S_COMPLETE);
122178828Sdfr	}
123178828Sdfr	return (major_status);
124178828Sdfr}
125178828Sdfr
126