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