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 : krb5_context context;
42 : gsskrb5_cred cred, dup;
43 : 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 : HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
77 :
78 0 : dup->destination_realm = NULL;
79 0 : if (cred->destination_realm &&
80 0 : (dup->destination_realm = strdup(cred->destination_realm)) == NULL) {
81 0 : *minor_status = krb5_enomem(context);
82 0 : free(dup);
83 0 : return (GSS_S_FAILURE);
84 : }
85 0 : dup->usage = cred->usage;
86 0 : dup->endtime = cred->endtime;
87 0 : dup->principal = NULL;
88 0 : dup->keytab = NULL;
89 0 : dup->ccache = NULL;
90 0 : dup->mechanisms = NULL;
91 :
92 0 : major = GSS_S_FAILURE;
93 :
94 : HEIMDAL_MUTEX_init(&dup->cred_id_mutex);
95 0 : *minor_status = krb5_copy_principal(context, cred->principal,
96 : &dup->principal);
97 0 : if (*minor_status)
98 0 : goto fail;
99 :
100 0 : if (cred->keytab) {
101 0 : char *name = NULL;
102 :
103 0 : *minor_status = krb5_kt_get_full_name(context, cred->keytab, &name);
104 0 : if (*minor_status)
105 0 : goto fail;
106 0 : *minor_status = krb5_kt_resolve(context, name, &dup->keytab);
107 0 : krb5_xfree(name);
108 0 : if (*minor_status)
109 0 : goto fail;
110 : }
111 :
112 0 : if (cred->ccache) {
113 : const char *type, *name;
114 0 : char *type_name = NULL;
115 :
116 0 : type = krb5_cc_get_type(context, cred->ccache); /* can't fail */
117 0 : if (strcmp(type, "MEMORY") == 0) {
118 0 : *minor_status = krb5_cc_new_unique(context, type, NULL,
119 0 : &dup->ccache);
120 0 : if (*minor_status)
121 0 : goto fail;
122 :
123 0 : *minor_status = krb5_cc_copy_cache(context, cred->ccache,
124 : dup->ccache);
125 0 : if (*minor_status)
126 0 : goto fail;
127 :
128 : } else {
129 0 : name = krb5_cc_get_name(context, cred->ccache);
130 0 : if (name == NULL) {
131 0 : *minor_status = ENOMEM;
132 0 : goto fail;
133 : }
134 :
135 0 : if (asprintf(&type_name, "%s:%s", type, name) == -1 ||
136 0 : type_name == NULL) {
137 0 : *minor_status = ENOMEM;
138 0 : goto fail;
139 : }
140 :
141 0 : *minor_status = krb5_cc_resolve(context, type_name,
142 0 : &dup->ccache);
143 0 : free(type_name);
144 0 : if (*minor_status)
145 0 : goto fail;
146 : }
147 : }
148 :
149 0 : major = gss_create_empty_oid_set(minor_status, &dup->mechanisms);
150 0 : if (major != GSS_S_COMPLETE)
151 0 : goto fail;
152 :
153 0 : major = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
154 : &dup->mechanisms);
155 0 : if (major != GSS_S_COMPLETE)
156 0 : goto fail;
157 :
158 : HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
159 0 : *output_cred_handle = (gss_cred_id_t)dup;
160 0 : *minor_status = 0;
161 0 : return major;
162 :
163 0 : fail:
164 : HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
165 0 : *output_cred_handle = (gss_cred_id_t)dup;
166 0 : _gsskrb5_release_cred(&junk, output_cred_handle);
167 0 : return major;
168 : }
|