1 /*
2 * Copyright 2008-2010 by the Massachusetts Institute of Technology.
3 * All Rights Reserved.
4 *
5 * Export of this software from the United States of America may
6 * require a specific license from the United States Government.
7 * It is the responsibility of any person or organization contemplating
8 * export to obtain such a license before exporting.
9 *
10 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
11 * distribute this software and its documentation for any purpose and
12 * without fee is hereby granted, provided that the above copyright
13 * notice appear in all copies and that both that copyright notice and
14 * this permission notice appear in supporting documentation, and that
15 * the name of M.I.T. not be used in advertising or publicity pertaining
16 * to distribution of the software without specific, written prior
17 * permission. Furthermore if you modify this software you must label
18 * your software as modified software and not distribute it in such a
19 * fashion that it might be confused with the original M.I.T. software.
20 * M.I.T. makes no representations about the suitability of
21 * this software for any purpose. It is provided "as is" without express
22 * or implied warranty.
23 */
24
25 /* Glue routine for gssspi_set_cred_option */
26
27 #include "mglueP.h"
28 #include <stdio.h>
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #include <string.h>
33 #include <time.h>
34
35 static OM_uint32
alloc_union_cred(OM_uint32 * minor_status,gss_mechanism mech,gss_cred_id_t mech_cred,gss_union_cred_t * pcred)36 alloc_union_cred(OM_uint32 *minor_status,
37 gss_mechanism mech,
38 gss_cred_id_t mech_cred,
39 gss_union_cred_t *pcred)
40 {
41 OM_uint32 status;
42 OM_uint32 temp_minor_status;
43 gss_union_cred_t cred = NULL;
44
45 *pcred = NULL;
46
47 status = GSS_S_FAILURE;
48
49 cred = calloc(1, sizeof(*cred));
50 if (cred == NULL) {
51 *minor_status = ENOMEM;
52 goto cleanup;
53 }
54
55 cred->loopback = cred;
56 cred->count = 1;
57
58 cred->cred_array = calloc(cred->count, sizeof(gss_cred_id_t));
59 if (cred->cred_array == NULL) {
60 *minor_status = ENOMEM;
61 goto cleanup;
62 }
63 cred->cred_array[0] = mech_cred;
64
65 status = generic_gss_copy_oid(minor_status,
66 &mech->mech_type,
67 &cred->mechs_array);
68 if (status != GSS_S_COMPLETE)
69 goto cleanup;
70
71 status = GSS_S_COMPLETE;
72 *pcred = cred;
73
74 cleanup:
75 if (status != GSS_S_COMPLETE)
76 gss_release_cred(&temp_minor_status, (gss_cred_id_t *)&cred);
77
78 return status;
79 }
80
81 /*
82 * This differs from gssspi_set_cred_option() as shipped in 1.7, in that
83 * it can return a cred handle. To denote this change we have changed the
84 * name of the function from gssspi_set_cred_option() to gss_set_cred_option().
85 * However, the dlsym() entry point is still gssspi_set_cred_option(). This
86 * fixes a separate issue, namely that a dynamically loaded mechanism could
87 * not itself call set_cred_option() without calling its own implementation
88 * instead of the mechanism glue's. (This is useful where a mechanism wishes
89 * to export a mechanism-specific API that is a wrapper around this function.)
90 */
91 OM_uint32 KRB5_CALLCONV
gss_set_cred_option(OM_uint32 * minor_status,gss_cred_id_t * cred_handle,const gss_OID desired_object,const gss_buffer_t value)92 gss_set_cred_option(OM_uint32 *minor_status,
93 gss_cred_id_t *cred_handle,
94 const gss_OID desired_object,
95 const gss_buffer_t value)
96 {
97 gss_union_cred_t union_cred;
98 gss_mechanism mech;
99 int i;
100 OM_uint32 status;
101 OM_uint32 mech_status;
102 OM_uint32 mech_minor_status;
103
104 if (minor_status == NULL)
105 return GSS_S_CALL_INACCESSIBLE_WRITE;
106 *minor_status = 0;
107
108 if (cred_handle == NULL)
109 return GSS_S_CALL_INACCESSIBLE_WRITE;
110
111 status = GSS_S_UNAVAILABLE;
112
113 if (*cred_handle == GSS_C_NO_CREDENTIAL) {
114 gss_cred_id_t mech_cred = GSS_C_NO_CREDENTIAL;
115
116 /*
117 * We need to give a mechanism the opportunity to allocate a
118 * credentials handle. Unfortunately this does mean that only
119 * the default mechanism can allocate a credentials handle.
120 */
121 mech = gssint_get_mechanism(NULL);
122 if (mech == NULL)
123 return GSS_S_BAD_MECH;
124
125 if (mech->gssspi_set_cred_option == NULL)
126 return GSS_S_UNAVAILABLE;
127
128 status = mech->gssspi_set_cred_option(minor_status,
129 &mech_cred,
130 desired_object,
131 value);
132 if (status != GSS_S_COMPLETE) {
133 map_error(minor_status, mech);
134 return status;
135 }
136
137 if (mech_cred != GSS_C_NO_CREDENTIAL) {
138 status = alloc_union_cred(minor_status,
139 mech,
140 mech_cred,
141 &union_cred);
142 if (status != GSS_S_COMPLETE)
143 return status;
144 *cred_handle = (gss_cred_id_t)union_cred;
145 }
146 } else {
147 union_cred = (gss_union_cred_t)*cred_handle;
148
149 for (i = 0; i < union_cred->count; i++) {
150 mech = gssint_get_mechanism(&union_cred->mechs_array[i]);
151 if (mech == NULL) {
152 status = GSS_S_BAD_MECH;
153 break;
154 }
155
156 if (mech->gssspi_set_cred_option == NULL)
157 continue;
158
159 mech_status = mech->gssspi_set_cred_option(&mech_minor_status,
160 &union_cred->cred_array[i],
161 desired_object,
162 value);
163 if (mech_status == GSS_S_UNAVAILABLE)
164 continue;
165 else {
166 status = mech_status;
167 *minor_status = mech_minor_status;
168 }
169 if (status != GSS_S_COMPLETE) {
170 map_error(minor_status, mech);
171 break;
172 }
173 }
174 }
175
176 return status;
177 }
178
179 /*
180 * Provide this for backward ABI compatibility, but remove it from the
181 * header.
182 */
183 OM_uint32 KRB5_CALLCONV
184 gssspi_set_cred_option(OM_uint32 *minor_status,
185 gss_cred_id_t cred,
186 const gss_OID desired_object,
187 const gss_buffer_t value);
188
189 OM_uint32 KRB5_CALLCONV
gssspi_set_cred_option(OM_uint32 * minor_status,gss_cred_id_t cred,const gss_OID desired_object,const gss_buffer_t value)190 gssspi_set_cred_option(OM_uint32 *minor_status,
191 gss_cred_id_t cred,
192 const gss_OID desired_object,
193 const gss_buffer_t value)
194 {
195 return gss_set_cred_option(minor_status, &cred,
196 desired_object, value);
197 }
198