2 * Copyright (c) 2018 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "gsskrb5_locl.h"
36 OM_uint32 GSSAPI_CALLCONV
_gsskrb5_duplicate_cred (
37 OM_uint32
*minor_status
,
38 gss_const_cred_id_t input_cred_handle
,
39 gss_cred_id_t
*output_cred_handle
)
42 gsskrb5_cred cred
, dup
;
43 OM_uint32 major
, junk
;
47 if (output_cred_handle
== NULL
) {
48 *minor_status
= EINVAL
;
49 return GSS_S_CALL_INACCESSIBLE_WRITE
;
52 GSSAPI_KRB5_INIT (&context
);
54 if (input_cred_handle
== GSS_C_NO_CREDENTIAL
) {
55 /* Duplicate the default credential */
56 return _gsskrb5_acquire_cred_from(minor_status
, GSS_C_NO_NAME
,
65 /* Duplicate the input credential */
67 dup
= calloc(1, sizeof(*dup
));
69 *minor_status
= krb5_enomem(context
);
70 return (GSS_S_FAILURE
);
73 *output_cred_handle
= (gss_cred_id_t
)dup
; /* making sure to release on error */
75 cred
= (gsskrb5_cred
)input_cred_handle
;
76 HEIMDAL_MUTEX_lock(&cred
->cred_id_mutex
);
78 dup
->destination_realm
= NULL
;
79 dup
->usage
= cred
->usage
;
80 dup
->endtime
= cred
->endtime
;
81 dup
->principal
= NULL
;
84 dup
->mechanisms
= NULL
;
86 major
= GSS_S_FAILURE
;
88 HEIMDAL_MUTEX_init(&dup
->cred_id_mutex
);
89 if (cred
->destination_realm
&&
90 (dup
->destination_realm
= strdup(cred
->destination_realm
)) == NULL
) {
91 *minor_status
= krb5_enomem(context
);
94 *minor_status
= krb5_copy_principal(context
, cred
->principal
,
102 *minor_status
= krb5_kt_get_full_name(context
, cred
->keytab
, &name
);
105 *minor_status
= krb5_kt_resolve(context
, name
, &dup
->keytab
);
112 const char *type
, *name
;
113 char *type_name
= NULL
;
115 type
= krb5_cc_get_type(context
, cred
->ccache
); /* can't fail */
116 if (strcmp(type
, "MEMORY") == 0) {
117 *minor_status
= krb5_cc_new_unique(context
, type
, NULL
,
122 *minor_status
= krb5_cc_copy_cache(context
, cred
->ccache
,
128 name
= krb5_cc_get_name(context
, cred
->ccache
);
130 *minor_status
= ENOMEM
;
134 if (asprintf(&type_name
, "%s:%s", type
, name
) == -1 ||
136 *minor_status
= ENOMEM
;
140 *minor_status
= krb5_cc_resolve(context
, type_name
,
148 major
= gss_create_empty_oid_set(minor_status
, &dup
->mechanisms
);
149 if (major
!= GSS_S_COMPLETE
)
152 major
= gss_add_oid_set_member(minor_status
, GSS_KRB5_MECHANISM
,
154 if (major
!= GSS_S_COMPLETE
)
157 HEIMDAL_MUTEX_unlock(&cred
->cred_id_mutex
);
158 *output_cred_handle
= (gss_cred_id_t
)dup
;
163 HEIMDAL_MUTEX_unlock(&cred
->cred_id_mutex
);
164 *output_cred_handle
= (gss_cred_id_t
)dup
;
165 _gsskrb5_release_cred(&junk
, output_cred_handle
);