1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright 2009 by the Massachusetts Institute of Technology.
6 * Export of this software from the United States of America may
7 * require a specific license from the United States Government.
8 * It is the responsibility of any person or organization contemplating
9 * export to obtain such a license before exporting.
11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12 * distribute this software and its documentation for any purpose and
13 * without fee is hereby granted, provided that the above copyright
14 * notice appear in all copies and that both that copyright notice and
15 * this permission notice appear in supporting documentation, and that
16 * the name of M.I.T. not be used in advertising or publicity pertaining
17 * to distribution of the software without specific, written prior
18 * permission. Furthermore if you modify this software you must label
19 * your software as modified software and not distribute it in such a
20 * fashion that it might be confused with the original M.I.T. software.
21 * M.I.T. makes no representations about the suitability of
22 * this software for any purpose. It is provided "as is" without express
23 * or implied warranty.
26 #include "gssapiP_krb5.h"
33 kg_is_initiator_cred(krb5_gss_cred_id_t cred)
35 return (cred->usage == GSS_C_INITIATE || cred->usage == GSS_C_BOTH) &&
36 (cred->ccache != NULL);
40 kg_impersonate_name(OM_uint32 *minor_status,
41 const krb5_gss_cred_id_t impersonator_cred,
42 const krb5_gss_name_t user,
44 krb5_gss_cred_id_t *output_cred,
48 OM_uint32 major_status;
50 krb5_creds in_creds, *out_creds = NULL;
53 memset(&in_creds, 0, sizeof(in_creds));
55 in_creds.client = user->princ;
56 in_creds.server = impersonator_cred->name->princ;
58 if (impersonator_cred->req_enctypes != NULL)
59 in_creds.keyblock.enctype = impersonator_cred->req_enctypes[0];
61 code = k5_mutex_lock(&user->lock);
67 if (user->ad_context != NULL) {
68 code = krb5_authdata_export_authdata(context,
73 k5_mutex_unlock(&user->lock);
79 k5_mutex_unlock(&user->lock);
81 code = krb5_get_credentials_for_user(context,
82 KRB5_GC_CANONICALIZE | KRB5_GC_NO_STORE,
83 impersonator_cred->ccache,
87 krb5_free_authdata(context, in_creds.authdata);
92 major_status = kg_compose_deleg_cred(minor_status,
100 krb5_free_authdata(context, in_creds.authdata);
101 krb5_free_creds(context, out_creds);
106 /* The mechglue always passes null desired_mechs and actual_mechs. */
107 OM_uint32 KRB5_CALLCONV
108 krb5_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
109 const gss_cred_id_t impersonator_cred_handle,
110 const gss_name_t desired_name,
112 const gss_OID_set desired_mechs,
113 gss_cred_usage_t cred_usage,
114 gss_cred_id_t *output_cred_handle,
115 gss_OID_set *actual_mechs,
118 OM_uint32 major_status;
119 krb5_error_code code;
120 krb5_gss_cred_id_t cred;
121 krb5_context context;
123 if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL)
124 return GSS_S_CALL_INACCESSIBLE_READ;
126 if (desired_name == GSS_C_NO_NAME)
127 return GSS_S_CALL_INACCESSIBLE_READ;
129 if (output_cred_handle == NULL)
130 return GSS_S_CALL_INACCESSIBLE_WRITE;
132 if (cred_usage != GSS_C_INITIATE) {
133 *minor_status = (OM_uint32)G_BAD_USAGE;
134 return GSS_S_FAILURE;
137 *output_cred_handle = GSS_C_NO_CREDENTIAL;
138 if (time_rec != NULL)
141 code = krb5_gss_init_context(&context);
143 *minor_status = code;
144 return GSS_S_FAILURE;
147 major_status = kg_cred_resolve(minor_status, context,
148 impersonator_cred_handle, NULL);
149 if (GSS_ERROR(major_status)) {
150 krb5_free_context(context);
154 major_status = kg_impersonate_name(minor_status,
155 (krb5_gss_cred_id_t)impersonator_cred_handle,
156 (krb5_gss_name_t)desired_name,
162 if (!GSS_ERROR(major_status))
163 *output_cred_handle = (gss_cred_id_t)cred;
165 k5_mutex_unlock(&((krb5_gss_cred_id_t)impersonator_cred_handle)->lock);
166 krb5_free_context(context);
173 kg_compose_deleg_cred(OM_uint32 *minor_status,
174 krb5_gss_cred_id_t impersonator_cred,
175 krb5_creds *subject_creds,
177 krb5_gss_cred_id_t *output_cred,
179 krb5_context context)
181 OM_uint32 major_status;
182 krb5_error_code code;
183 krb5_gss_cred_id_t cred = NULL;
186 k5_mutex_assert_locked(&impersonator_cred->lock);
188 if (!kg_is_initiator_cred(impersonator_cred) ||
189 impersonator_cred->name == NULL ||
190 impersonator_cred->proxy_cred) {
195 assert(impersonator_cred->name->princ != NULL);
197 assert(subject_creds != NULL);
198 assert(subject_creds->client != NULL);
200 cred = xmalloc(sizeof(*cred));
205 memset(cred, 0, sizeof(*cred));
207 code = k5_mutex_init(&cred->lock);
212 * Only return a "proxy" credential for use with constrained
213 * delegation if the subject credentials are forwardable.
214 * Submitting non-forwardable credentials to the KDC for use
215 * with constrained delegation will only return an error.
217 cred->usage = GSS_C_INITIATE;
218 cred->proxy_cred = !!(subject_creds->ticket_flags & TKT_FLG_FORWARDABLE);
220 cred->tgt_expire = subject_creds->times.endtime;
222 code = kg_init_name(context, subject_creds->client, NULL, NULL, NULL, 0,
227 code = krb5_cc_new_unique(context, "MEMORY", NULL, &cred->ccache);
230 cred->destroy_ccache = 1;
232 code = krb5_cc_initialize(context, cred->ccache,
233 cred->proxy_cred ? impersonator_cred->name->princ :
234 subject_creds->client);
238 if (cred->proxy_cred) {
239 /* Impersonator's TGT will be necessary for S4U2Proxy */
240 code = krb5_cc_copy_creds(context, impersonator_cred->ccache,
246 code = krb5_cc_store_cred(context, cred->ccache, subject_creds);
250 if (time_rec != NULL) {
253 code = krb5_timeofday(context, &now);
257 *time_rec = cred->tgt_expire - now;
260 major_status = GSS_S_COMPLETE;
266 *minor_status = code;
267 major_status = GSS_S_FAILURE;
270 if (GSS_ERROR(major_status) && cred != NULL) {
271 k5_mutex_destroy(&cred->lock);
272 krb5_cc_destroy(context, cred->ccache);
273 kg_release_name(context, &cred->name);