1178825Sdfr/*
2233294Sstas * Copyright (c) 1997, 2003 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34233294Sstas#include "gsskrb5_locl.h"
35178825Sdfr
36233294SstasOM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred
37178825Sdfr(OM_uint32 * minor_status,
38178825Sdfr const gss_cred_id_t cred_handle,
39178825Sdfr gss_name_t * output_name,
40178825Sdfr OM_uint32 * lifetime,
41178825Sdfr gss_cred_usage_t * cred_usage,
42178825Sdfr gss_OID_set * mechanisms
43178825Sdfr    )
44178825Sdfr{
45178825Sdfr    krb5_context context;
46178825Sdfr    gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL;
47178825Sdfr    gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL;
48178825Sdfr    gsskrb5_cred acred = NULL, icred = NULL;
49178825Sdfr    OM_uint32 ret;
50178825Sdfr
51178825Sdfr    *minor_status = 0;
52178825Sdfr
53178825Sdfr    if (output_name)
54178825Sdfr	*output_name = NULL;
55178825Sdfr    if (mechanisms)
56178825Sdfr	*mechanisms = GSS_C_NO_OID_SET;
57178825Sdfr
58178825Sdfr    GSSAPI_KRB5_INIT (&context);
59178825Sdfr
60178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
61233294Sstas	ret = _gsskrb5_acquire_cred(minor_status,
62178825Sdfr				    GSS_C_NO_NAME,
63178825Sdfr				    GSS_C_INDEFINITE,
64178825Sdfr				    GSS_C_NO_OID_SET,
65178825Sdfr				    GSS_C_ACCEPT,
66178825Sdfr				    &aqcred_accept,
67178825Sdfr				    NULL,
68178825Sdfr				    NULL);
69178825Sdfr	if (ret == GSS_S_COMPLETE)
70178825Sdfr	    acred = (gsskrb5_cred)aqcred_accept;
71178825Sdfr
72233294Sstas	ret = _gsskrb5_acquire_cred(minor_status,
73178825Sdfr				    GSS_C_NO_NAME,
74178825Sdfr				    GSS_C_INDEFINITE,
75178825Sdfr				    GSS_C_NO_OID_SET,
76178825Sdfr				    GSS_C_INITIATE,
77178825Sdfr				    &aqcred_init,
78178825Sdfr				    NULL,
79178825Sdfr				    NULL);
80178825Sdfr	if (ret == GSS_S_COMPLETE)
81178825Sdfr	    icred = (gsskrb5_cred)aqcred_init;
82178825Sdfr
83178825Sdfr	if (icred == NULL && acred == NULL) {
84178825Sdfr	    *minor_status = 0;
85178825Sdfr	    return GSS_S_NO_CRED;
86178825Sdfr	}
87178825Sdfr    } else
88178825Sdfr	acred = (gsskrb5_cred)cred_handle;
89178825Sdfr
90178825Sdfr    if (acred)
91178825Sdfr	HEIMDAL_MUTEX_lock(&acred->cred_id_mutex);
92178825Sdfr    if (icred)
93178825Sdfr	HEIMDAL_MUTEX_lock(&icred->cred_id_mutex);
94178825Sdfr
95178825Sdfr    if (output_name != NULL) {
96178825Sdfr	if (icred && icred->principal != NULL) {
97178825Sdfr	    gss_name_t name;
98233294Sstas
99178825Sdfr	    if (acred && acred->principal)
100178825Sdfr		name = (gss_name_t)acred->principal;
101178825Sdfr	    else
102178825Sdfr		name = (gss_name_t)icred->principal;
103233294Sstas
104178825Sdfr            ret = _gsskrb5_duplicate_name(minor_status, name, output_name);
105178825Sdfr            if (ret)
106178825Sdfr		goto out;
107178825Sdfr	} else if (acred && acred->usage == GSS_C_ACCEPT) {
108178825Sdfr	    krb5_principal princ;
109178825Sdfr	    *minor_status = krb5_sname_to_principal(context, NULL,
110233294Sstas						    NULL, KRB5_NT_SRV_HST,
111178825Sdfr						    &princ);
112178825Sdfr	    if (*minor_status) {
113178825Sdfr		ret = GSS_S_FAILURE;
114178825Sdfr		goto out;
115178825Sdfr	    }
116178825Sdfr	    *output_name = (gss_name_t)princ;
117178825Sdfr	} else {
118178825Sdfr	    krb5_principal princ;
119178825Sdfr	    *minor_status = krb5_get_default_principal(context,
120178825Sdfr						       &princ);
121178825Sdfr	    if (*minor_status) {
122178825Sdfr		ret = GSS_S_FAILURE;
123178825Sdfr		goto out;
124178825Sdfr	    }
125178825Sdfr	    *output_name = (gss_name_t)princ;
126178825Sdfr	}
127178825Sdfr    }
128178825Sdfr    if (lifetime != NULL) {
129178825Sdfr	OM_uint32 alife = GSS_C_INDEFINITE, ilife = GSS_C_INDEFINITE;
130178825Sdfr
131178825Sdfr	if (acred) alife = acred->lifetime;
132178825Sdfr	if (icred) ilife = icred->lifetime;
133178825Sdfr
134233294Sstas	ret = _gsskrb5_lifetime_left(minor_status,
135178825Sdfr				     context,
136178825Sdfr				     min(alife,ilife),
137178825Sdfr				     lifetime);
138178825Sdfr	if (ret)
139178825Sdfr	    goto out;
140178825Sdfr    }
141178825Sdfr    if (cred_usage != NULL) {
142178825Sdfr	if (acred && icred)
143178825Sdfr	    *cred_usage = GSS_C_BOTH;
144178825Sdfr	else if (acred)
145178825Sdfr	    *cred_usage = GSS_C_ACCEPT;
146178825Sdfr	else if (icred)
147178825Sdfr	    *cred_usage = GSS_C_INITIATE;
148178825Sdfr	else
149178825Sdfr	    abort();
150178825Sdfr    }
151178825Sdfr
152178825Sdfr    if (mechanisms != NULL) {
153178825Sdfr        ret = gss_create_empty_oid_set(minor_status, mechanisms);
154178825Sdfr        if (ret)
155178825Sdfr	    goto out;
156178825Sdfr	if (acred)
157178825Sdfr	    ret = gss_add_oid_set_member(minor_status,
158178825Sdfr					 &acred->mechanisms->elements[0],
159178825Sdfr					 mechanisms);
160178825Sdfr	if (ret == GSS_S_COMPLETE && icred)
161178825Sdfr	    ret = gss_add_oid_set_member(minor_status,
162178825Sdfr					 &icred->mechanisms->elements[0],
163178825Sdfr					 mechanisms);
164178825Sdfr        if (ret)
165178825Sdfr	    goto out;
166178825Sdfr    }
167178825Sdfr    ret = GSS_S_COMPLETE;
168178825Sdfrout:
169178825Sdfr    if (acred)
170178825Sdfr	HEIMDAL_MUTEX_unlock(&acred->cred_id_mutex);
171178825Sdfr    if (icred)
172178825Sdfr	HEIMDAL_MUTEX_unlock(&icred->cred_id_mutex);
173178825Sdfr
174178825Sdfr    if (aqcred_init != GSS_C_NO_CREDENTIAL)
175178825Sdfr	ret = _gsskrb5_release_cred(minor_status, &aqcred_init);
176178825Sdfr    if (aqcred_accept != GSS_C_NO_CREDENTIAL)
177178825Sdfr	ret = _gsskrb5_release_cred(minor_status, &aqcred_accept);
178178825Sdfr
179178825Sdfr    return ret;
180178825Sdfr}
181