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