1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * COPYRIGHT (C) 2006,2007 4 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN 5 * ALL RIGHTS RESERVED 6 * 7 * Permission is granted to use, copy, create derivative works 8 * and redistribute this software and such derivative works 9 * for any purpose, so long as the name of The University of 10 * Michigan is not used in any advertising or publicity 11 * pertaining to the use of distribution of this software 12 * without specific, written prior authorization. If the 13 * above copyright notice or any other identification of the 14 * University of Michigan is included in any copy of any 15 * portion of this software, then the disclaimer below must 16 * also be included. 17 * 18 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 19 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 20 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 21 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 22 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 24 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 25 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 26 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 27 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 28 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGES. 30 */ 31 32 #include "k5-int.h" 33 #include "pkinit.h" 34 35 /* 36 * Routines for handling profile [config file] options 37 */ 38 39 /* Forward prototypes */ 40 static int _krb5_conf_boolean(const char *s); 41 42 /* 43 * XXX 44 * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c, 45 * which is duplicated from somewhere else. :-/ 46 * XXX 47 */ 48 static const char *const conf_yes[] = { 49 "y", "yes", "true", "t", "1", "on", 50 0, 51 }; 52 53 static const char *const conf_no[] = { 54 "n", "no", "false", "nil", "0", "off", 55 0, 56 }; 57 58 static int 59 _krb5_conf_boolean(const char *s) 60 { 61 const char *const *p; 62 63 for(p=conf_yes; *p; p++) { 64 if (strcasecmp(*p,s) == 0) 65 return 1; 66 } 67 68 for(p=conf_no; *p; p++) { 69 if (strcasecmp(*p,s) == 0) 70 return 0; 71 } 72 73 /* Default to "no" */ 74 return 0; 75 } 76 77 /* 78 * XXX 79 * End duplicated code from src/lib/krb5/krb/get_in_tkt.c 80 * XXX 81 */ 82 83 /* 84 * The following are based on krb5_libdefault_* functions in 85 * src/lib/krb5/krb/get_in_tkt.c 86 * N.B. This assumes that context->default_realm has 87 * already been established. 88 */ 89 krb5_error_code 90 pkinit_kdcdefault_strings(krb5_context context, const char *realmname, 91 const char *option, char ***ret_value) 92 { 93 profile_t profile = NULL; 94 const char *names[5]; 95 char **values = NULL; 96 krb5_error_code retval; 97 98 if (context == NULL) 99 return KV5M_CONTEXT; 100 101 profile = context->profile; 102 103 if (realmname != NULL) { 104 /* 105 * Try number one: 106 * 107 * [realms] 108 * REALM = { 109 * option = <value> 110 * } 111 */ 112 113 names[0] = KRB5_CONF_REALMS; 114 names[1] = realmname; 115 names[2] = option; 116 names[3] = 0; 117 retval = profile_get_values(profile, names, &values); 118 if (retval == 0 && values != NULL) 119 goto goodbye; 120 } 121 122 /* 123 * Try number two: 124 * 125 * [kdcdefaults] 126 * option = <value> 127 */ 128 129 names[0] = KRB5_CONF_KDCDEFAULTS; 130 names[1] = option; 131 names[2] = 0; 132 retval = profile_get_values(profile, names, &values); 133 if (retval == 0 && values != NULL) 134 goto goodbye; 135 136 goodbye: 137 if (values == NULL) 138 retval = ENOENT; 139 140 *ret_value = values; 141 142 return retval; 143 144 } 145 146 krb5_error_code 147 pkinit_kdcdefault_string(krb5_context context, const char *realmname, 148 const char *option, char **ret_value) 149 { 150 krb5_error_code retval; 151 char **values = NULL; 152 153 retval = pkinit_kdcdefault_strings(context, realmname, option, &values); 154 if (retval) 155 return retval; 156 157 if (values[0] == NULL) { 158 retval = ENOENT; 159 } else { 160 *ret_value = strdup(values[0]); 161 if (*ret_value == NULL) 162 retval = ENOMEM; 163 } 164 165 profile_free_list(values); 166 return retval; 167 } 168 169 krb5_error_code 170 pkinit_kdcdefault_boolean(krb5_context context, const char *realmname, 171 const char *option, int default_value, int *ret_value) 172 { 173 char *string = NULL; 174 krb5_error_code retval; 175 176 retval = pkinit_kdcdefault_string(context, realmname, option, &string); 177 178 if (retval == 0) { 179 *ret_value = _krb5_conf_boolean(string); 180 free(string); 181 } else 182 *ret_value = default_value; 183 184 return 0; 185 } 186 187 krb5_error_code 188 pkinit_kdcdefault_integer(krb5_context context, const char *realmname, 189 const char *option, int default_value, int *ret_value) 190 { 191 char *string = NULL; 192 krb5_error_code retval; 193 194 retval = pkinit_kdcdefault_string(context, realmname, option, &string); 195 196 if (retval == 0) { 197 char *endptr; 198 long l; 199 l = strtol(string, &endptr, 0); 200 if (endptr == string) 201 *ret_value = default_value; 202 else 203 *ret_value = l; 204 free(string); 205 } else 206 *ret_value = default_value; 207 208 return 0; 209 } 210 211 212 /* 213 * krb5_libdefault_string() is defined as static in 214 * src/lib/krb5/krb/get_in_tkt.c. Create local versions of 215 * krb5_libdefault_* functions here. We need a libdefaults_strings() 216 * function which is not currently supported there anyway. Also, 217 * add the ability to supply a default value for the boolean and 218 * integer functions. 219 */ 220 221 krb5_error_code 222 pkinit_libdefault_strings(krb5_context context, const krb5_data *realm, 223 const char *option, char ***ret_value) 224 { 225 profile_t profile; 226 const char *names[5]; 227 char **values = NULL; 228 krb5_error_code retval; 229 char realmstr[1024]; 230 231 if (realm != NULL && realm->length > sizeof(realmstr)-1) 232 return EINVAL; 233 234 if (realm != NULL) { 235 strncpy(realmstr, realm->data, realm->length); 236 realmstr[realm->length] = '\0'; 237 } 238 239 if (!context || (context->magic != KV5M_CONTEXT)) 240 return KV5M_CONTEXT; 241 242 profile = context->profile; 243 244 245 if (realm != NULL) { 246 /* 247 * Try number one: 248 * 249 * [libdefaults] 250 * REALM = { 251 * option = <value> 252 * } 253 */ 254 255 names[0] = KRB5_CONF_LIBDEFAULTS; 256 names[1] = realmstr; 257 names[2] = option; 258 names[3] = 0; 259 retval = profile_get_values(profile, names, &values); 260 if (retval == 0 && values != NULL && values[0] != NULL) 261 goto goodbye; 262 263 /* 264 * Try number two: 265 * 266 * [realms] 267 * REALM = { 268 * option = <value> 269 * } 270 */ 271 272 names[0] = KRB5_CONF_REALMS; 273 names[1] = realmstr; 274 names[2] = option; 275 names[3] = 0; 276 retval = profile_get_values(profile, names, &values); 277 if (retval == 0 && values != NULL && values[0] != NULL) 278 goto goodbye; 279 } 280 281 /* 282 * Try number three: 283 * 284 * [libdefaults] 285 * option = <value> 286 */ 287 288 names[0] = KRB5_CONF_LIBDEFAULTS; 289 names[1] = option; 290 names[2] = 0; 291 retval = profile_get_values(profile, names, &values); 292 if (retval == 0 && values != NULL && values[0] != NULL) 293 goto goodbye; 294 295 goodbye: 296 if (values == NULL) 297 return ENOENT; 298 299 *ret_value = values; 300 301 return retval; 302 } 303 304 krb5_error_code 305 pkinit_libdefault_string(krb5_context context, const krb5_data *realm, 306 const char *option, char **ret_value) 307 { 308 krb5_error_code retval; 309 char **values = NULL; 310 311 retval = pkinit_libdefault_strings(context, realm, option, &values); 312 if (retval) 313 return retval; 314 315 if (values[0] == NULL) { 316 retval = ENOENT; 317 } else { 318 *ret_value = strdup(values[0]); 319 if (*ret_value == NULL) 320 retval = ENOMEM; 321 } 322 323 profile_free_list(values); 324 return retval; 325 } 326 327 krb5_error_code 328 pkinit_libdefault_boolean(krb5_context context, const krb5_data *realm, 329 const char *option, int default_value, 330 int *ret_value) 331 { 332 char *string = NULL; 333 krb5_error_code retval; 334 335 retval = pkinit_libdefault_string(context, realm, option, &string); 336 337 if (retval == 0) { 338 *ret_value = _krb5_conf_boolean(string); 339 free(string); 340 } else 341 *ret_value = default_value; 342 343 return 0; 344 } 345 346 krb5_error_code 347 pkinit_libdefault_integer(krb5_context context, const krb5_data *realm, 348 const char *option, int default_value, 349 int *ret_value) 350 { 351 char *string = NULL; 352 krb5_error_code retval; 353 354 retval = pkinit_libdefault_string(context, realm, option, &string); 355 356 if (retval == 0) { 357 char *endptr; 358 long l; 359 l = strtol(string, &endptr, 0); 360 if (endptr == string) 361 *ret_value = default_value; 362 else 363 *ret_value = l; 364 free(string); 365 } 366 367 return retval; 368 } 369