1c19800e8SDoug Rabson /*
2c19800e8SDoug Rabson * Copyright (c) 2004, PADL Software Pty Ltd.
3c19800e8SDoug Rabson * All rights reserved.
4c19800e8SDoug Rabson *
5c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
6c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
7c19800e8SDoug Rabson * are met:
8c19800e8SDoug Rabson *
9c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
10c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
11c19800e8SDoug Rabson *
12c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
13c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
14c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
15c19800e8SDoug Rabson *
16c19800e8SDoug Rabson * 3. Neither the name of PADL Software nor the names of its contributors
17c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
18c19800e8SDoug Rabson * without specific prior written permission.
19c19800e8SDoug Rabson *
20c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c19800e8SDoug Rabson * SUCH DAMAGE.
31c19800e8SDoug Rabson */
32c19800e8SDoug Rabson
33c19800e8SDoug Rabson /*
34c19800e8SDoug Rabson * glue routine for _gsskrb5_inquire_sec_context_by_oid
35c19800e8SDoug Rabson */
36c19800e8SDoug Rabson
37*ae771770SStanislav Sedov #include "gsskrb5_locl.h"
38c19800e8SDoug Rabson
39c19800e8SDoug Rabson static OM_uint32
get_bool(OM_uint32 * minor_status,const gss_buffer_t value,int * flag)40c19800e8SDoug Rabson get_bool(OM_uint32 *minor_status,
41c19800e8SDoug Rabson const gss_buffer_t value,
42c19800e8SDoug Rabson int *flag)
43c19800e8SDoug Rabson {
44c19800e8SDoug Rabson if (value->value == NULL || value->length != 1) {
45c19800e8SDoug Rabson *minor_status = EINVAL;
46c19800e8SDoug Rabson return GSS_S_FAILURE;
47c19800e8SDoug Rabson }
48c19800e8SDoug Rabson *flag = *((const char *)value->value) != 0;
49c19800e8SDoug Rabson return GSS_S_COMPLETE;
50c19800e8SDoug Rabson }
51c19800e8SDoug Rabson
52c19800e8SDoug Rabson static OM_uint32
get_string(OM_uint32 * minor_status,const gss_buffer_t value,char ** str)53c19800e8SDoug Rabson get_string(OM_uint32 *minor_status,
54c19800e8SDoug Rabson const gss_buffer_t value,
55c19800e8SDoug Rabson char **str)
56c19800e8SDoug Rabson {
57c19800e8SDoug Rabson if (value == NULL || value->length == 0) {
58c19800e8SDoug Rabson *str = NULL;
59c19800e8SDoug Rabson } else {
60c19800e8SDoug Rabson *str = malloc(value->length + 1);
61c19800e8SDoug Rabson if (*str == NULL) {
62c19800e8SDoug Rabson *minor_status = 0;
63c19800e8SDoug Rabson return GSS_S_UNAVAILABLE;
64c19800e8SDoug Rabson }
65c19800e8SDoug Rabson memcpy(*str, value->value, value->length);
66c19800e8SDoug Rabson (*str)[value->length] = '\0';
67c19800e8SDoug Rabson }
68c19800e8SDoug Rabson return GSS_S_COMPLETE;
69c19800e8SDoug Rabson }
70c19800e8SDoug Rabson
71*ae771770SStanislav Sedov static OM_uint32
get_int32(OM_uint32 * minor_status,const gss_buffer_t value,OM_uint32 * ret)72*ae771770SStanislav Sedov get_int32(OM_uint32 *minor_status,
73*ae771770SStanislav Sedov const gss_buffer_t value,
74*ae771770SStanislav Sedov OM_uint32 *ret)
75*ae771770SStanislav Sedov {
76*ae771770SStanislav Sedov *minor_status = 0;
77*ae771770SStanislav Sedov if (value == NULL || value->length == 0)
78*ae771770SStanislav Sedov *ret = 0;
79*ae771770SStanislav Sedov else if (value->length == sizeof(*ret))
80*ae771770SStanislav Sedov memcpy(ret, value->value, sizeof(*ret));
81*ae771770SStanislav Sedov else
82*ae771770SStanislav Sedov return GSS_S_UNAVAILABLE;
83*ae771770SStanislav Sedov
84*ae771770SStanislav Sedov return GSS_S_COMPLETE;
85*ae771770SStanislav Sedov }
86*ae771770SStanislav Sedov
87*ae771770SStanislav Sedov static OM_uint32
set_int32(OM_uint32 * minor_status,const gss_buffer_t value,OM_uint32 set)88*ae771770SStanislav Sedov set_int32(OM_uint32 *minor_status,
89*ae771770SStanislav Sedov const gss_buffer_t value,
90*ae771770SStanislav Sedov OM_uint32 set)
91*ae771770SStanislav Sedov {
92*ae771770SStanislav Sedov *minor_status = 0;
93*ae771770SStanislav Sedov if (value->length == sizeof(set))
94*ae771770SStanislav Sedov memcpy(value->value, &set, sizeof(set));
95*ae771770SStanislav Sedov else
96*ae771770SStanislav Sedov return GSS_S_UNAVAILABLE;
97*ae771770SStanislav Sedov
98*ae771770SStanislav Sedov return GSS_S_COMPLETE;
99*ae771770SStanislav Sedov }
100*ae771770SStanislav Sedov
101*ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV
_gsskrb5_set_sec_context_option(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,const gss_OID desired_object,const gss_buffer_t value)102c19800e8SDoug Rabson _gsskrb5_set_sec_context_option
103c19800e8SDoug Rabson (OM_uint32 *minor_status,
104c19800e8SDoug Rabson gss_ctx_id_t *context_handle,
105c19800e8SDoug Rabson const gss_OID desired_object,
106c19800e8SDoug Rabson const gss_buffer_t value)
107c19800e8SDoug Rabson {
108c19800e8SDoug Rabson krb5_context context;
109c19800e8SDoug Rabson OM_uint32 maj_stat;
110c19800e8SDoug Rabson
111c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context);
112c19800e8SDoug Rabson
113c19800e8SDoug Rabson if (value == GSS_C_NO_BUFFER) {
114c19800e8SDoug Rabson *minor_status = EINVAL;
115c19800e8SDoug Rabson return GSS_S_FAILURE;
116c19800e8SDoug Rabson }
117c19800e8SDoug Rabson
118c19800e8SDoug Rabson if (gss_oid_equal(desired_object, GSS_KRB5_COMPAT_DES3_MIC_X)) {
119c19800e8SDoug Rabson gsskrb5_ctx ctx;
120c19800e8SDoug Rabson int flag;
121c19800e8SDoug Rabson
122c19800e8SDoug Rabson if (*context_handle == GSS_C_NO_CONTEXT) {
123c19800e8SDoug Rabson *minor_status = EINVAL;
124c19800e8SDoug Rabson return GSS_S_NO_CONTEXT;
125c19800e8SDoug Rabson }
126c19800e8SDoug Rabson
127c19800e8SDoug Rabson maj_stat = get_bool(minor_status, value, &flag);
128c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
129c19800e8SDoug Rabson return maj_stat;
130c19800e8SDoug Rabson
131c19800e8SDoug Rabson ctx = (gsskrb5_ctx)*context_handle;
132c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
133c19800e8SDoug Rabson if (flag)
134c19800e8SDoug Rabson ctx->more_flags |= COMPAT_OLD_DES3;
135c19800e8SDoug Rabson else
136c19800e8SDoug Rabson ctx->more_flags &= ~COMPAT_OLD_DES3;
137c19800e8SDoug Rabson ctx->more_flags |= COMPAT_OLD_DES3_SELECTED;
138c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
139c19800e8SDoug Rabson return GSS_S_COMPLETE;
140c19800e8SDoug Rabson } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DNS_CANONICALIZE_X)) {
141c19800e8SDoug Rabson int flag;
142c19800e8SDoug Rabson
143c19800e8SDoug Rabson maj_stat = get_bool(minor_status, value, &flag);
144c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
145c19800e8SDoug Rabson return maj_stat;
146c19800e8SDoug Rabson
147c19800e8SDoug Rabson krb5_set_dns_canonicalize_hostname(context, flag);
148c19800e8SDoug Rabson return GSS_S_COMPLETE;
149c19800e8SDoug Rabson
150c19800e8SDoug Rabson } else if (gss_oid_equal(desired_object, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X)) {
151c19800e8SDoug Rabson char *str;
152c19800e8SDoug Rabson
153c19800e8SDoug Rabson maj_stat = get_string(minor_status, value, &str);
154c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
155c19800e8SDoug Rabson return maj_stat;
156c19800e8SDoug Rabson
157*ae771770SStanislav Sedov maj_stat = _gsskrb5_register_acceptor_identity(minor_status, str);
158c19800e8SDoug Rabson free(str);
159c19800e8SDoug Rabson
160*ae771770SStanislav Sedov return maj_stat;
161c19800e8SDoug Rabson
162c19800e8SDoug Rabson } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DEFAULT_REALM_X)) {
163c19800e8SDoug Rabson char *str;
164c19800e8SDoug Rabson
165c19800e8SDoug Rabson maj_stat = get_string(minor_status, value, &str);
166c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
167c19800e8SDoug Rabson return maj_stat;
168c19800e8SDoug Rabson if (str == NULL) {
169c19800e8SDoug Rabson *minor_status = 0;
170c19800e8SDoug Rabson return GSS_S_CALL_INACCESSIBLE_READ;
171c19800e8SDoug Rabson }
172c19800e8SDoug Rabson
173c19800e8SDoug Rabson krb5_set_default_realm(context, str);
174c19800e8SDoug Rabson free(str);
175c19800e8SDoug Rabson
176c19800e8SDoug Rabson *minor_status = 0;
177c19800e8SDoug Rabson return GSS_S_COMPLETE;
178c19800e8SDoug Rabson
179c19800e8SDoug Rabson } else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) {
180c19800e8SDoug Rabson
181c19800e8SDoug Rabson if (value == NULL || value->length == 0) {
182c19800e8SDoug Rabson krb5_set_send_to_kdc_func(context, NULL, NULL);
183c19800e8SDoug Rabson } else {
184c19800e8SDoug Rabson struct gsskrb5_send_to_kdc c;
185c19800e8SDoug Rabson
186c19800e8SDoug Rabson if (value->length != sizeof(c)) {
187c19800e8SDoug Rabson *minor_status = EINVAL;
188c19800e8SDoug Rabson return GSS_S_FAILURE;
189c19800e8SDoug Rabson }
190c19800e8SDoug Rabson memcpy(&c, value->value, sizeof(c));
191c19800e8SDoug Rabson krb5_set_send_to_kdc_func(context,
192c19800e8SDoug Rabson (krb5_send_to_kdc_func)c.func,
193c19800e8SDoug Rabson c.ptr);
194c19800e8SDoug Rabson }
195c19800e8SDoug Rabson
196c19800e8SDoug Rabson *minor_status = 0;
197c19800e8SDoug Rabson return GSS_S_COMPLETE;
198c19800e8SDoug Rabson } else if (gss_oid_equal(desired_object, GSS_KRB5_CCACHE_NAME_X)) {
199c19800e8SDoug Rabson char *str;
200c19800e8SDoug Rabson
201c19800e8SDoug Rabson maj_stat = get_string(minor_status, value, &str);
202c19800e8SDoug Rabson if (maj_stat != GSS_S_COMPLETE)
203c19800e8SDoug Rabson return maj_stat;
204c19800e8SDoug Rabson if (str == NULL) {
205c19800e8SDoug Rabson *minor_status = 0;
206c19800e8SDoug Rabson return GSS_S_CALL_INACCESSIBLE_READ;
207c19800e8SDoug Rabson }
208c19800e8SDoug Rabson
209c19800e8SDoug Rabson *minor_status = krb5_cc_set_default_name(context, str);
210c19800e8SDoug Rabson free(str);
211c19800e8SDoug Rabson if (*minor_status)
212c19800e8SDoug Rabson return GSS_S_FAILURE;
213c19800e8SDoug Rabson
214c19800e8SDoug Rabson return GSS_S_COMPLETE;
215*ae771770SStanislav Sedov } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_TIME_OFFSET_X)) {
216*ae771770SStanislav Sedov OM_uint32 offset;
217*ae771770SStanislav Sedov time_t t;
218*ae771770SStanislav Sedov
219*ae771770SStanislav Sedov maj_stat = get_int32(minor_status, value, &offset);
220*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
221*ae771770SStanislav Sedov return maj_stat;
222*ae771770SStanislav Sedov
223*ae771770SStanislav Sedov t = time(NULL) + offset;
224*ae771770SStanislav Sedov
225*ae771770SStanislav Sedov krb5_set_real_time(context, t, 0);
226*ae771770SStanislav Sedov
227*ae771770SStanislav Sedov *minor_status = 0;
228*ae771770SStanislav Sedov return GSS_S_COMPLETE;
229*ae771770SStanislav Sedov } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_TIME_OFFSET_X)) {
230*ae771770SStanislav Sedov krb5_timestamp sec;
231*ae771770SStanislav Sedov int32_t usec;
232*ae771770SStanislav Sedov time_t t;
233*ae771770SStanislav Sedov
234*ae771770SStanislav Sedov t = time(NULL);
235*ae771770SStanislav Sedov
236*ae771770SStanislav Sedov krb5_us_timeofday (context, &sec, &usec);
237*ae771770SStanislav Sedov
238*ae771770SStanislav Sedov maj_stat = set_int32(minor_status, value, sec - t);
239*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
240*ae771770SStanislav Sedov return maj_stat;
241*ae771770SStanislav Sedov
242*ae771770SStanislav Sedov *minor_status = 0;
243*ae771770SStanislav Sedov return GSS_S_COMPLETE;
244*ae771770SStanislav Sedov } else if (gss_oid_equal(desired_object, GSS_KRB5_PLUGIN_REGISTER_X)) {
245*ae771770SStanislav Sedov struct gsskrb5_krb5_plugin c;
246*ae771770SStanislav Sedov
247*ae771770SStanislav Sedov if (value->length != sizeof(c)) {
248*ae771770SStanislav Sedov *minor_status = EINVAL;
249*ae771770SStanislav Sedov return GSS_S_FAILURE;
250*ae771770SStanislav Sedov }
251*ae771770SStanislav Sedov memcpy(&c, value->value, sizeof(c));
252*ae771770SStanislav Sedov krb5_plugin_register(context, c.type, c.name, c.symbol);
253*ae771770SStanislav Sedov
254*ae771770SStanislav Sedov *minor_status = 0;
255*ae771770SStanislav Sedov return GSS_S_COMPLETE;
256c19800e8SDoug Rabson }
257c19800e8SDoug Rabson
258c19800e8SDoug Rabson *minor_status = EINVAL;
259c19800e8SDoug Rabson return GSS_S_FAILURE;
260c19800e8SDoug Rabson }
261