Line data Source code
1 : /*
2 : * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "gsskrb5_locl.h"
35 :
36 10607 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred
37 : (OM_uint32 * minor_status,
38 : gss_const_cred_id_t cred_handle,
39 : gss_name_t * output_name,
40 : OM_uint32 * lifetime,
41 : gss_cred_usage_t * cred_usage,
42 : gss_OID_set * mechanisms
43 : )
44 : {
45 450 : krb5_context context;
46 10607 : gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL;
47 10607 : gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL;
48 10607 : gsskrb5_cred cred = (gsskrb5_cred)cred_handle;
49 10607 : gss_OID_set amechs = GSS_C_NO_OID_SET;
50 10607 : gss_OID_set imechs = GSS_C_NO_OID_SET;
51 450 : OM_uint32 junk;
52 450 : OM_uint32 aminor;
53 450 : OM_uint32 ret;
54 450 : OM_uint32 aret;
55 10607 : OM_uint32 alife = GSS_C_INDEFINITE;
56 10607 : OM_uint32 ilife = GSS_C_INDEFINITE;
57 :
58 : /*
59 : * XXX This function is more complex than it has to be. It should call
60 : * _gsskrb5_inquire_cred_by_mech() twice and merge the results in the
61 : * cred_handle == GSS_C_NO_CREDENTIAL case, but since
62 : * _gsskrb5_inquire_cred_by_mech() is implemented in terms of this
63 : * function, first we must fix _gsskrb5_inquire_cred_by_mech().
64 : */
65 :
66 10607 : *minor_status = 0;
67 :
68 10607 : if (output_name)
69 10607 : *output_name = GSS_C_NO_NAME;
70 10607 : if (cred_usage)
71 10607 : *cred_usage = GSS_C_BOTH; /* There's no NONE */
72 10607 : if (mechanisms)
73 0 : *mechanisms = GSS_C_NO_OID_SET;
74 :
75 10607 : GSSAPI_KRB5_INIT (&context);
76 :
77 10607 : if (cred_handle == GSS_C_NO_CREDENTIAL) {
78 : /*
79 : * From here to the end of this if we should refactor into a separate
80 : * function.
81 : */
82 : /* Get the info for the default ACCEPT credential */
83 0 : aret = _gsskrb5_acquire_cred_from(&aminor,
84 : GSS_C_NO_NAME,
85 : GSS_C_INDEFINITE,
86 : GSS_C_NO_OID_SET,
87 : GSS_C_ACCEPT,
88 : GSS_C_NO_CRED_STORE,
89 : &aqcred_accept,
90 : NULL,
91 : NULL);
92 0 : if (aret == GSS_S_COMPLETE) {
93 0 : aret = _gsskrb5_inquire_cred(&aminor,
94 : aqcred_accept,
95 : output_name,
96 : &alife,
97 : NULL,
98 : &amechs);
99 0 : (void) _gsskrb5_release_cred(&junk, &aqcred_accept);
100 0 : if (aret == GSS_S_COMPLETE) {
101 0 : output_name = NULL; /* Can't merge names; output only one */
102 0 : if (cred_usage)
103 0 : *cred_usage = GSS_C_ACCEPT;
104 0 : if (lifetime)
105 0 : *lifetime = alife;
106 0 : if (mechanisms) {
107 0 : *mechanisms = amechs;
108 0 : amechs = GSS_C_NO_OID_SET;
109 : }
110 0 : (void) gss_release_oid_set(&junk, &amechs);
111 0 : } else if (aret != GSS_S_NO_CRED) {
112 0 : *minor_status = aminor;
113 0 : return aret;
114 : } else {
115 0 : alife = GSS_C_INDEFINITE;
116 : }
117 : }
118 :
119 : /* Get the info for the default INITIATE credential */
120 0 : ret = _gsskrb5_acquire_cred_from(minor_status,
121 : GSS_C_NO_NAME,
122 : GSS_C_INDEFINITE,
123 : GSS_C_NO_OID_SET,
124 : GSS_C_INITIATE,
125 : GSS_C_NO_CRED_STORE,
126 : &aqcred_init,
127 : NULL,
128 : NULL);
129 0 : if (ret == GSS_S_COMPLETE) {
130 0 : ret = _gsskrb5_inquire_cred(minor_status,
131 : aqcred_init,
132 : output_name,
133 : &ilife,
134 : NULL,
135 : &imechs);
136 0 : (void) _gsskrb5_release_cred(&junk, &aqcred_init);
137 0 : if (ret == GSS_S_COMPLETE) {
138 : /*
139 : * Merge results for INITIATE with ACCEPT if we had ACCEPT and
140 : * for those outputs that are desired.
141 : */
142 0 : if (cred_usage) {
143 0 : *cred_usage = (*cred_usage == GSS_C_ACCEPT) ?
144 0 : GSS_C_BOTH : GSS_C_INITIATE;
145 : }
146 0 : if (lifetime)
147 0 : *lifetime = min(alife, ilife);
148 0 : if (mechanisms) {
149 : /*
150 : * This is just one mechanism (IAKERB and such would live
151 : * elsewhere). imechs will be equal to amechs, though not
152 : * ==.
153 : */
154 0 : if (aret != GSS_S_COMPLETE) {
155 0 : *mechanisms = imechs;
156 0 : imechs = GSS_C_NO_OID_SET;
157 : }
158 : }
159 0 : (void) gss_release_oid_set(&junk, &amechs);
160 0 : } else if (ret != GSS_S_NO_CRED) {
161 0 : *minor_status = aminor;
162 0 : return aret;
163 : }
164 : }
165 :
166 0 : if (aret != GSS_S_COMPLETE && ret != GSS_S_COMPLETE) {
167 0 : *minor_status = aminor;
168 0 : return aret;
169 : }
170 0 : *minor_status = 0; /* Even though 0 is not specified to be special */
171 0 : return GSS_S_COMPLETE;
172 : }
173 :
174 450 : HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
175 :
176 10607 : if (output_name != NULL) {
177 10607 : if (cred->principal != NULL) {
178 10607 : gss_name_t name = (gss_name_t)cred->principal;
179 10607 : ret = _gsskrb5_duplicate_name(minor_status, name, output_name);
180 10607 : if (ret)
181 0 : goto out;
182 0 : } else if (cred->usage == GSS_C_ACCEPT) {
183 : /*
184 : * Keytab case, princ may not be set (yet, ever, whatever).
185 : *
186 : * We used to unconditionally output the krb5_sname_to_principal()
187 : * of the host service for the hostname, but we didn't know if we
188 : * had keytab entries for it, so it was incorrect. We can't be
189 : * breaking anything in tree by outputting GSS_C_NO_NAME, but we
190 : * might be breaking other callers.
191 : */
192 0 : *output_name = GSS_C_NO_NAME;
193 : } else {
194 : /* This shouldn't happen */
195 0 : *minor_status = KRB5_NOCREDS_SUPPLIED; /* XXX */
196 0 : ret = GSS_S_NO_CRED;
197 0 : goto out;
198 : }
199 : }
200 10607 : if (lifetime != NULL) {
201 11057 : ret = _gsskrb5_lifetime_left(minor_status,
202 : context,
203 10607 : cred->endtime,
204 : lifetime);
205 10607 : if (ret)
206 0 : goto out;
207 : }
208 10607 : if (cred_usage != NULL)
209 10607 : *cred_usage = cred->usage;
210 10607 : if (mechanisms != NULL) {
211 0 : ret = gss_create_empty_oid_set(minor_status, mechanisms);
212 0 : if (ret)
213 0 : goto out;
214 0 : ret = gss_add_oid_set_member(minor_status,
215 0 : &cred->mechanisms->elements[0],
216 : mechanisms);
217 0 : if (ret)
218 0 : goto out;
219 : }
220 10157 : ret = GSS_S_COMPLETE;
221 :
222 10157 : out:
223 : HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
224 10157 : return ret;
225 : }
|