set_sec_context_option.c revision 256281
190075Sobrien/* 2132718Skan * Copyright (c) 2004, PADL Software Pty Ltd. 3132718Skan * All rights reserved. 490075Sobrien * 590075Sobrien * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 790075Sobrien * are met: 890075Sobrien * 990075Sobrien * 1. Redistributions of source code must retain the above copyright 1090075Sobrien * notice, this list of conditions and the following disclaimer. 1190075Sobrien * 1290075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1390075Sobrien * notice, this list of conditions and the following disclaimer in the 1490075Sobrien * documentation and/or other materials provided with the distribution. 1590075Sobrien * 1690075Sobrien * 3. Neither the name of PADL Software nor the names of its contributors 1790075Sobrien * may be used to endorse or promote products derived from this software 1890075Sobrien * without specific prior written permission. 1990075Sobrien * 2090075Sobrien * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 2190075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2290075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2390075Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 2490075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2590075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2690075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2790075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28132718Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29132718Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3090075Sobrien * SUCH DAMAGE. 31132718Skan */ 32132718Skan 3390075Sobrien/* 3490075Sobrien * glue routine for _gsskrb5_inquire_sec_context_by_oid 35132718Skan */ 3690075Sobrien 3790075Sobrien#include "gsskrb5_locl.h" 3890075Sobrien 39117395Skanstatic OM_uint32 40117395Skanget_bool(OM_uint32 *minor_status, 41132718Skan const gss_buffer_t value, 42117395Skan int *flag) 43132718Skan{ 44132718Skan if (value->value == NULL || value->length != 1) { 45132718Skan *minor_status = EINVAL; 46132718Skan return GSS_S_FAILURE; 47132718Skan } 48132718Skan *flag = *((const char *)value->value) != 0; 49132718Skan return GSS_S_COMPLETE; 50132718Skan} 51132718Skan 52132718Skanstatic OM_uint32 53132718Skanget_string(OM_uint32 *minor_status, 54132718Skan const gss_buffer_t value, 55117395Skan char **str) 56117395Skan{ 57117395Skan if (value == NULL || value->length == 0) { 58117395Skan *str = NULL; 59132718Skan } else { 60117395Skan *str = malloc(value->length + 1); 61117395Skan if (*str == NULL) { 62117395Skan *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 71static OM_uint32 72get_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 87static OM_uint32 88set_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 101OM_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} 261