1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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
29 #include <gssapi/gssapi.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "mech_switch.h"
35 #include "name.h"
36 #include "cred.h"
37
38 #define AUSAGE 1
39 #define IUSAGE 2
40
41 static void
updateusage(gss_cred_usage_t usage,int * usagemask)42 updateusage(gss_cred_usage_t usage, int *usagemask)
43 {
44 if (usage == GSS_C_BOTH)
45 *usagemask |= AUSAGE | IUSAGE;
46 else if (usage == GSS_C_ACCEPT)
47 *usagemask |= AUSAGE;
48 else if (usage == GSS_C_INITIATE)
49 *usagemask |= IUSAGE;
50 }
51
52 OM_uint32
gss_inquire_cred(OM_uint32 * minor_status,const gss_cred_id_t cred_handle,gss_name_t * name_ret,OM_uint32 * lifetime,gss_cred_usage_t * cred_usage,gss_OID_set * mechanisms)53 gss_inquire_cred(OM_uint32 *minor_status,
54 const gss_cred_id_t cred_handle,
55 gss_name_t *name_ret,
56 OM_uint32 *lifetime,
57 gss_cred_usage_t *cred_usage,
58 gss_OID_set *mechanisms)
59 {
60 OM_uint32 major_status;
61 struct _gss_mech_switch *m;
62 struct _gss_cred *cred = (struct _gss_cred *) cred_handle;
63 struct _gss_name *name;
64 struct _gss_mechanism_name *mn;
65 OM_uint32 min_lifetime;
66 int found = 0;
67 int usagemask = 0;
68 gss_cred_usage_t usage;
69
70 _gss_load_mech();
71
72 *minor_status = 0;
73 if (name_ret)
74 *name_ret = GSS_C_NO_NAME;
75 if (lifetime)
76 *lifetime = 0;
77 if (cred_usage)
78 *cred_usage = 0;
79 if (mechanisms)
80 *mechanisms = GSS_C_NO_OID_SET;
81
82 if (name_ret) {
83 name = malloc(sizeof(struct _gss_name));
84 if (name == NULL) {
85 *minor_status = ENOMEM;
86 return (GSS_S_FAILURE);
87 }
88 memset(name, 0, sizeof(struct _gss_name));
89 SLIST_INIT(&name->gn_mn);
90 } else {
91 name = NULL;
92 }
93
94 if (mechanisms) {
95 major_status = gss_create_empty_oid_set(minor_status,
96 mechanisms);
97 if (major_status) {
98 if (name) free(name);
99 return (major_status);
100 }
101 }
102
103 min_lifetime = GSS_C_INDEFINITE;
104 if (cred) {
105 struct _gss_mechanism_cred *mc;
106
107 SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
108 gss_name_t mc_name;
109 OM_uint32 mc_lifetime;
110
111 major_status = mc->gmc_mech->gm_inquire_cred(minor_status,
112 mc->gmc_cred, &mc_name, &mc_lifetime, &usage, NULL);
113 if (major_status)
114 continue;
115
116 updateusage(usage, &usagemask);
117 if (name && mc_name) {
118 mn = malloc(sizeof(struct _gss_mechanism_name));
119 if (!mn) {
120 mc->gmc_mech->gm_release_name(minor_status,
121 &mc_name);
122 continue;
123 }
124 mn->gmn_mech = mc->gmc_mech;
125 mn->gmn_mech_oid = mc->gmc_mech_oid;
126 mn->gmn_name = mc_name;
127 SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
128 } else if (mc_name) {
129 mc->gmc_mech->gm_release_name(minor_status,
130 &mc_name);
131 }
132
133 if (mc_lifetime < min_lifetime)
134 min_lifetime = mc_lifetime;
135
136 if (mechanisms)
137 gss_add_oid_set_member(minor_status,
138 mc->gmc_mech_oid, mechanisms);
139 found++;
140 }
141 } else {
142 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
143 gss_name_t mc_name;
144 OM_uint32 mc_lifetime;
145
146 major_status = m->gm_inquire_cred(minor_status,
147 GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime,
148 &usage, NULL);
149 if (major_status)
150 continue;
151
152 updateusage(usage, &usagemask);
153 if (name && mc_name) {
154 mn = malloc(
155 sizeof(struct _gss_mechanism_name));
156 if (!mn) {
157 m->gm_release_name(
158 minor_status, &mc_name);
159 continue;
160 }
161 mn->gmn_mech = m;
162 mn->gmn_mech_oid = &m->gm_mech_oid;
163 mn->gmn_name = mc_name;
164 SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
165 } else if (mc_name) {
166 m->gm_release_name(minor_status,
167 &mc_name);
168 }
169
170 if (mc_lifetime < min_lifetime)
171 min_lifetime = mc_lifetime;
172
173 if (mechanisms)
174 gss_add_oid_set_member(minor_status,
175 &m->gm_mech_oid, mechanisms);
176 found++;
177 }
178 }
179
180 if (found == 0) {
181 gss_name_t n = (gss_name_t)name;
182 if (n)
183 gss_release_name(minor_status, &n);
184 gss_release_oid_set(minor_status, mechanisms);
185 *minor_status = 0;
186 return (GSS_S_NO_CRED);
187 }
188
189 *minor_status = 0;
190 if (name_ret)
191 *name_ret = (gss_name_t) name;
192 if (lifetime)
193 *lifetime = min_lifetime;
194 if (cred_usage) {
195 if ((usagemask & (AUSAGE|IUSAGE)) == (AUSAGE|IUSAGE))
196 *cred_usage = GSS_C_BOTH;
197 else if (usagemask & IUSAGE)
198 *cred_usage = GSS_C_INITIATE;
199 else if (usagemask & AUSAGE)
200 *cred_usage = GSS_C_ACCEPT;
201 }
202 return (GSS_S_COMPLETE);
203 }
204