1226031Sstas/*
2226031Sstas * Copyright (c) 2004, PADL Software Pty Ltd.
3226031Sstas * All rights reserved.
4226031Sstas *
5226031Sstas * Redistribution and use in source and binary forms, with or without
6226031Sstas * modification, are permitted provided that the following conditions
7226031Sstas * are met:
8226031Sstas *
9226031Sstas * 1. Redistributions of source code must retain the above copyright
10226031Sstas *    notice, this list of conditions and the following disclaimer.
11226031Sstas *
12226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
13226031Sstas *    notice, this list of conditions and the following disclaimer in the
14226031Sstas *    documentation and/or other materials provided with the distribution.
15226031Sstas *
16226031Sstas * 3. Neither the name of PADL Software nor the names of its contributors
17226031Sstas *    may be used to endorse or promote products derived from this software
18226031Sstas *    without specific prior written permission.
19226031Sstas *
20226031Sstas * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30226031Sstas * SUCH DAMAGE.
31226031Sstas */
32226031Sstas
33226031Sstas#include "mech_locl.h"
34226031Sstas
35226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
36226031Sstasgss_set_cred_option (OM_uint32 *minor_status,
37226031Sstas		     gss_cred_id_t *cred_handle,
38226031Sstas		     const gss_OID object,
39226031Sstas		     const gss_buffer_t value)
40226031Sstas{
41226031Sstas	struct _gss_cred *cred = (struct _gss_cred *) *cred_handle;
42226031Sstas	OM_uint32	major_status = GSS_S_COMPLETE;
43226031Sstas	struct _gss_mechanism_cred *mc;
44226031Sstas	int one_ok = 0;
45226031Sstas
46226031Sstas	*minor_status = 0;
47226031Sstas
48226031Sstas	_gss_load_mech();
49226031Sstas
50226031Sstas	if (cred == NULL) {
51226031Sstas		struct _gss_mech_switch *m;
52226031Sstas
53226031Sstas		cred = malloc(sizeof(*cred));
54226031Sstas		if (cred == NULL)
55226031Sstas		    return GSS_S_FAILURE;
56226031Sstas
57226031Sstas		HEIM_SLIST_INIT(&cred->gc_mc);
58226031Sstas
59226031Sstas		HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
60226031Sstas
61226031Sstas			if (m->gm_mech.gm_set_cred_option == NULL)
62226031Sstas				continue;
63226031Sstas
64226031Sstas			mc = malloc(sizeof(*mc));
65226031Sstas			if (mc == NULL) {
66226031Sstas			    *cred_handle = (gss_cred_id_t)cred;
67226031Sstas			    gss_release_cred(minor_status, cred_handle);
68226031Sstas			    *minor_status = ENOMEM;
69226031Sstas			    return GSS_S_FAILURE;
70226031Sstas			}
71226031Sstas
72226031Sstas			mc->gmc_mech = &m->gm_mech;
73226031Sstas			mc->gmc_mech_oid = &m->gm_mech_oid;
74226031Sstas			mc->gmc_cred = GSS_C_NO_CREDENTIAL;
75226031Sstas
76226031Sstas			major_status = m->gm_mech.gm_set_cred_option(
77226031Sstas			    minor_status, &mc->gmc_cred, object, value);
78226031Sstas
79226031Sstas			if (major_status) {
80226031Sstas				free(mc);
81226031Sstas				continue;
82226031Sstas			}
83226031Sstas			one_ok = 1;
84226031Sstas			HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
85226031Sstas		}
86226031Sstas		*cred_handle = (gss_cred_id_t)cred;
87226031Sstas		if (!one_ok) {
88226031Sstas			OM_uint32 junk;
89226031Sstas			gss_release_cred(&junk, cred_handle);
90226031Sstas		}
91226031Sstas	} else {
92226031Sstas		gssapi_mech_interface	m;
93226031Sstas
94226031Sstas		HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
95226031Sstas			m = mc->gmc_mech;
96226031Sstas
97226031Sstas			if (m == NULL)
98226031Sstas				return GSS_S_BAD_MECH;
99226031Sstas
100226031Sstas			if (m->gm_set_cred_option == NULL)
101226031Sstas				continue;
102226031Sstas
103226031Sstas			major_status = m->gm_set_cred_option(minor_status,
104226031Sstas			    &mc->gmc_cred, object, value);
105226031Sstas			if (major_status == GSS_S_COMPLETE)
106226031Sstas				one_ok = 1;
107226031Sstas			else
108226031Sstas				_gss_mg_error(m, major_status, *minor_status);
109226031Sstas
110226031Sstas		}
111226031Sstas	}
112226031Sstas	if (one_ok) {
113226031Sstas		*minor_status = 0;
114226031Sstas		return GSS_S_COMPLETE;
115226031Sstas	}
116226031Sstas	return major_status;
117226031Sstas}
118226031Sstas
119