Line data Source code
1 : /*
2 : * Copyright (c) 2018 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 0 : 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)
40 : {
41 0 : krb5_context context;
42 0 : gsskrb5_cred cred, dup;
43 0 : OM_uint32 major, junk;
44 :
45 0 : dup = NULL;
46 :
47 0 : if (output_cred_handle == NULL) {
48 0 : *minor_status = EINVAL;
49 0 : return GSS_S_CALL_INACCESSIBLE_WRITE;
50 : }
51 :
52 0 : GSSAPI_KRB5_INIT (&context);
53 :
54 0 : if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
55 : /* Duplicate the default credential */
56 0 : return _gsskrb5_acquire_cred_from(minor_status, GSS_C_NO_NAME,
57 : GSS_C_INDEFINITE,
58 : GSS_C_NO_OID_SET,
59 : GSS_C_BOTH,
60 : GSS_C_NO_CRED_STORE,
61 : output_cred_handle,
62 : NULL, NULL);
63 : }
64 :
65 : /* Duplicate the input credential */
66 :
67 0 : dup = calloc(1, sizeof(*dup));
68 0 : if (dup == NULL) {
69 0 : *minor_status = krb5_enomem(context);
70 0 : return (GSS_S_FAILURE);
71 : }
72 :
73 0 : *output_cred_handle = (gss_cred_id_t)dup; /* making sure to release on error */
74 :
75 0 : cred = (gsskrb5_cred)input_cred_handle;
76 0 : HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
77 :
78 0 : dup->destination_realm = NULL;
79 0 : dup->usage = cred->usage;
80 0 : dup->endtime = cred->endtime;
81 0 : dup->principal = NULL;
82 0 : dup->keytab = NULL;
83 0 : dup->ccache = NULL;
84 0 : dup->mechanisms = NULL;
85 :
86 0 : major = GSS_S_FAILURE;
87 :
88 0 : HEIMDAL_MUTEX_init(&dup->cred_id_mutex);
89 0 : if (cred->destination_realm &&
90 0 : (dup->destination_realm = strdup(cred->destination_realm)) == NULL) {
91 0 : *minor_status = krb5_enomem(context);
92 0 : goto fail;
93 : }
94 0 : *minor_status = krb5_copy_principal(context, cred->principal,
95 : &dup->principal);
96 0 : if (*minor_status)
97 0 : goto fail;
98 :
99 0 : if (cred->keytab) {
100 0 : char *name = NULL;
101 :
102 0 : *minor_status = krb5_kt_get_full_name(context, cred->keytab, &name);
103 0 : if (*minor_status)
104 0 : goto fail;
105 0 : *minor_status = krb5_kt_resolve(context, name, &dup->keytab);
106 0 : krb5_xfree(name);
107 0 : if (*minor_status)
108 0 : goto fail;
109 : }
110 :
111 0 : if (cred->ccache) {
112 0 : const char *type, *name;
113 0 : char *type_name = NULL;
114 :
115 0 : type = krb5_cc_get_type(context, cred->ccache); /* can't fail */
116 0 : if (strcmp(type, "MEMORY") == 0) {
117 0 : *minor_status = krb5_cc_new_unique(context, type, NULL,
118 0 : &dup->ccache);
119 0 : if (*minor_status)
120 0 : goto fail;
121 :
122 0 : *minor_status = krb5_cc_copy_cache(context, cred->ccache,
123 : dup->ccache);
124 0 : if (*minor_status)
125 0 : goto fail;
126 :
127 : } else {
128 0 : name = krb5_cc_get_name(context, cred->ccache);
129 0 : if (name == NULL) {
130 0 : *minor_status = ENOMEM;
131 0 : goto fail;
132 : }
133 :
134 0 : if (asprintf(&type_name, "%s:%s", type, name) == -1 ||
135 0 : type_name == NULL) {
136 0 : *minor_status = ENOMEM;
137 0 : goto fail;
138 : }
139 :
140 0 : *minor_status = krb5_cc_resolve(context, type_name,
141 0 : &dup->ccache);
142 0 : free(type_name);
143 0 : if (*minor_status)
144 0 : goto fail;
145 : }
146 : }
147 :
148 0 : major = gss_create_empty_oid_set(minor_status, &dup->mechanisms);
149 0 : if (major != GSS_S_COMPLETE)
150 0 : goto fail;
151 :
152 0 : major = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
153 : &dup->mechanisms);
154 0 : if (major != GSS_S_COMPLETE)
155 0 : goto fail;
156 :
157 0 : HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
158 0 : *output_cred_handle = (gss_cred_id_t)dup;
159 0 : *minor_status = 0;
160 0 : return major;
161 :
162 0 : fail:
163 0 : HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
164 0 : *output_cred_handle = (gss_cred_id_t)dup;
165 0 : _gsskrb5_release_cred(&junk, output_cred_handle);
166 0 : return major;
167 : }
|