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