1 /*	$NetBSD: gss_inquire_cred.c,v 1.1.1.1 2011/04/13 18:14:46 elric Exp $	*/
2 
3 /*-
4  * Copyright (c) 2005 Doug Rabson
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *	$FreeBSD: src/lib/libgssapi/gss_inquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
29  */
30 
31 #include "mech_locl.h"
32 
33 #define AUSAGE 1
34 #define IUSAGE 2
35 
36 static void
37 updateusage(gss_cred_usage_t usage, int *usagemask)
38 {
39     if (usage == GSS_C_BOTH)
40 	*usagemask |= AUSAGE | IUSAGE;
41     else if (usage == GSS_C_ACCEPT)
42 	*usagemask |= AUSAGE;
43     else if (usage == GSS_C_INITIATE)
44 	*usagemask |= IUSAGE;
45 }
46 
47 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
48 gss_inquire_cred(OM_uint32 *minor_status,
49     const gss_cred_id_t cred_handle,
50     gss_name_t *name_ret,
51     OM_uint32 *lifetime,
52     gss_cred_usage_t *cred_usage,
53     gss_OID_set *mechanisms)
54 {
55 	OM_uint32 major_status;
56 	struct _gss_mech_switch *m;
57 	struct _gss_cred *cred = (struct _gss_cred *) cred_handle;
58 	struct _gss_name *name;
59 	struct _gss_mechanism_name *mn;
60 	OM_uint32 min_lifetime;
61 	int found = 0;
62 	int usagemask = 0;
63 	gss_cred_usage_t usage;
64 
65 	_gss_load_mech();
66 
67 	*minor_status = 0;
68 	if (name_ret)
69 		*name_ret = GSS_C_NO_NAME;
70 	if (lifetime)
71 		*lifetime = 0;
72 	if (cred_usage)
73 		*cred_usage = 0;
74 	if (mechanisms)
75 		*mechanisms = GSS_C_NO_OID_SET;
76 
77 	if (name_ret) {
78 		name = calloc(1, sizeof(*name));
79 		if (name == NULL) {
80 			*minor_status = ENOMEM;
81 			return (GSS_S_FAILURE);
82 		}
83 		HEIM_SLIST_INIT(&name->gn_mn);
84 	} else {
85 		name = NULL;
86 	}
87 
88 	if (mechanisms) {
89 		major_status = gss_create_empty_oid_set(minor_status,
90 		    mechanisms);
91 		if (major_status) {
92 			if (name) free(name);
93 			return (major_status);
94 		}
95 	}
96 
97 	min_lifetime = GSS_C_INDEFINITE;
98 	if (cred) {
99 		struct _gss_mechanism_cred *mc;
100 
101 		HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
102 			gss_name_t mc_name;
103 			OM_uint32 mc_lifetime;
104 
105 			major_status = mc->gmc_mech->gm_inquire_cred(minor_status,
106 			    mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL);
107 			if (major_status)
108 				continue;
109 
110 			updateusage(usage, &usagemask);
111 			if (name) {
112 				mn = malloc(sizeof(struct _gss_mechanism_name));
113 				if (!mn) {
114 					mc->gmc_mech->gm_release_name(minor_status,
115 					    &mc_name);
116 					continue;
117 				}
118 				mn->gmn_mech = mc->gmc_mech;
119 				mn->gmn_mech_oid = mc->gmc_mech_oid;
120 				mn->gmn_name = mc_name;
121 				HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
122 			} else {
123 				mc->gmc_mech->gm_release_name(minor_status,
124 				    &mc_name);
125 			}
126 
127 			if (mc_lifetime < min_lifetime)
128 				min_lifetime = mc_lifetime;
129 
130 			if (mechanisms)
131 				gss_add_oid_set_member(minor_status,
132 				    mc->gmc_mech_oid, mechanisms);
133 			found++;
134 		}
135 	} else {
136 		HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
137 			gss_name_t mc_name;
138 			OM_uint32 mc_lifetime;
139 
140 			major_status = m->gm_mech.gm_inquire_cred(minor_status,
141 			    GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime,
142 			    &usage, NULL);
143 			if (major_status)
144 				continue;
145 
146 			updateusage(usage, &usagemask);
147 			if (name && mc_name) {
148 				mn = malloc(
149 					sizeof(struct _gss_mechanism_name));
150 				if (!mn) {
151 					m->gm_mech.gm_release_name(
152 						minor_status, &mc_name);
153 					continue;
154 				}
155 				mn->gmn_mech = &m->gm_mech;
156 				mn->gmn_mech_oid = &m->gm_mech_oid;
157 				mn->gmn_name = mc_name;
158 				HEIM_SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
159 			} else if (mc_name) {
160 				m->gm_mech.gm_release_name(minor_status,
161 				    &mc_name);
162 			}
163 
164 			if (mc_lifetime < min_lifetime)
165 				min_lifetime = mc_lifetime;
166 
167 			if (mechanisms)
168 				gss_add_oid_set_member(minor_status,
169 				    &m->gm_mech_oid, mechanisms);
170 			found++;
171 		}
172 	}
173 
174 	if (found == 0) {
175 		gss_name_t n = (gss_name_t)name;
176 		if (n)
177 			gss_release_name(minor_status, &n);
178 		gss_release_oid_set(minor_status, mechanisms);
179 		*minor_status = 0;
180 		return (GSS_S_NO_CRED);
181 	}
182 
183 	*minor_status = 0;
184 	if (name_ret)
185 		*name_ret = (gss_name_t) name;
186 	if (lifetime)
187 		*lifetime = min_lifetime;
188 	if (cred_usage) {
189 		if ((usagemask & (AUSAGE|IUSAGE)) == (AUSAGE|IUSAGE))
190 			*cred_usage = GSS_C_BOTH;
191 		else if (usagemask & IUSAGE)
192 			*cred_usage = GSS_C_INITIATE;
193 		else if (usagemask & AUSAGE)
194 			*cred_usage = GSS_C_ACCEPT;
195 	}
196 	return (GSS_S_COMPLETE);
197 }
198