155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2004 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 755682Smarkm * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 1155682Smarkm * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 1455682Smarkm * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 1855682Smarkm * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 3455682Smarkm */ 3555682Smarkm 3655682Smarkm#include "krb5_locl.h" 3755682Smarkm 38233294Sstas#ifdef __APPLE__ 39233294Sstas#include <CoreFoundation/CoreFoundation.h> 40233294Sstas#endif 4155682Smarkm 42178825Sdfr/* Gaah! I want a portable funopen */ 43178825Sdfrstruct fileptr { 44178825Sdfr const char *s; 45178825Sdfr FILE *f; 46178825Sdfr}; 47178825Sdfr 48178825Sdfrstatic char * 49178825Sdfrconfig_fgets(char *str, size_t len, struct fileptr *ptr) 50178825Sdfr{ 51178825Sdfr /* XXX this is not correct, in that they don't do the same if the 52178825Sdfr line is longer than len */ 53178825Sdfr if(ptr->f != NULL) 54178825Sdfr return fgets(str, len, ptr->f); 55178825Sdfr else { 56178825Sdfr /* this is almost strsep_copy */ 57178825Sdfr const char *p; 58178825Sdfr ssize_t l; 59178825Sdfr if(*ptr->s == '\0') 60178825Sdfr return NULL; 61178825Sdfr p = ptr->s + strcspn(ptr->s, "\n"); 62178825Sdfr if(*p == '\n') 63178825Sdfr p++; 64233294Sstas l = min(len, (size_t)(p - ptr->s)); 65178825Sdfr if(len > 0) { 66178825Sdfr memcpy(str, ptr->s, l); 67178825Sdfr str[l] = '\0'; 68178825Sdfr } 69178825Sdfr ptr->s = p; 70178825Sdfr return str; 71178825Sdfr } 72178825Sdfr} 73178825Sdfr 7478527Sassarstatic krb5_error_code parse_section(char *p, krb5_config_section **s, 7578527Sassar krb5_config_section **res, 76233294Sstas const char **err_message); 77178825Sdfrstatic krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p, 7878527Sassar krb5_config_binding **b, 7978527Sassar krb5_config_binding **parent, 80233294Sstas const char **err_message); 81178825Sdfrstatic krb5_error_code parse_list(struct fileptr *f, unsigned *lineno, 8278527Sassar krb5_config_binding **parent, 83233294Sstas const char **err_message); 8455682Smarkm 85233294Sstaskrb5_config_section * 86233294Sstas_krb5_config_get_entry(krb5_config_section **parent, const char *name, int type) 87102644Snectar{ 88102644Snectar krb5_config_section **q; 89102644Snectar 90102644Snectar for(q = parent; *q != NULL; q = &(*q)->next) 91233294Sstas if(type == krb5_config_list && 92233294Sstas (unsigned)type == (*q)->type && 93102644Snectar strcmp(name, (*q)->name) == 0) 94102644Snectar return *q; 95102644Snectar *q = calloc(1, sizeof(**q)); 96102644Snectar if(*q == NULL) 97102644Snectar return NULL; 98102644Snectar (*q)->name = strdup(name); 99102644Snectar (*q)->type = type; 100102644Snectar if((*q)->name == NULL) { 101102644Snectar free(*q); 102102644Snectar *q = NULL; 103102644Snectar return NULL; 104102644Snectar } 105102644Snectar return *q; 106102644Snectar} 107102644Snectar 10855682Smarkm/* 10955682Smarkm * Parse a section: 11055682Smarkm * 11155682Smarkm * [section] 11255682Smarkm * foo = bar 11355682Smarkm * b = { 11455682Smarkm * a 11555682Smarkm * } 11655682Smarkm * ... 117233294Sstas * 11855682Smarkm * starting at the line in `p', storing the resulting structure in 11955682Smarkm * `s' and hooking it into `parent'. 120233294Sstas * Store the error message in `err_message'. 12155682Smarkm */ 12255682Smarkm 12378527Sassarstatic krb5_error_code 12455682Smarkmparse_section(char *p, krb5_config_section **s, krb5_config_section **parent, 125233294Sstas const char **err_message) 12655682Smarkm{ 12755682Smarkm char *p1; 12855682Smarkm krb5_config_section *tmp; 12955682Smarkm 13055682Smarkm p1 = strchr (p + 1, ']'); 13155682Smarkm if (p1 == NULL) { 132233294Sstas *err_message = "missing ]"; 13378527Sassar return KRB5_CONFIG_BADFORMAT; 13455682Smarkm } 13555682Smarkm *p1 = '\0'; 136233294Sstas tmp = _krb5_config_get_entry(parent, p + 1, krb5_config_list); 137102644Snectar if(tmp == NULL) { 138233294Sstas *err_message = "out of memory"; 13978527Sassar return KRB5_CONFIG_BADFORMAT; 14055682Smarkm } 14155682Smarkm *s = tmp; 14255682Smarkm return 0; 14355682Smarkm} 14455682Smarkm 14555682Smarkm/* 14655682Smarkm * Parse a brace-enclosed list from `f', hooking in the structure at 14755682Smarkm * `parent'. 148233294Sstas * Store the error message in `err_message'. 14955682Smarkm */ 15055682Smarkm 151127808Snectarstatic krb5_error_code 152178825Sdfrparse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent, 153233294Sstas const char **err_message) 15455682Smarkm{ 155233294Sstas char buf[KRB5_BUFSIZ]; 156127808Snectar krb5_error_code ret; 15755682Smarkm krb5_config_binding *b = NULL; 15855682Smarkm unsigned beg_lineno = *lineno; 15955682Smarkm 160178825Sdfr while(config_fgets(buf, sizeof(buf), f) != NULL) { 16155682Smarkm char *p; 16255682Smarkm 16355682Smarkm ++*lineno; 164178825Sdfr buf[strcspn(buf, "\r\n")] = '\0'; 16555682Smarkm p = buf; 16655682Smarkm while(isspace((unsigned char)*p)) 16755682Smarkm ++p; 16855682Smarkm if (*p == '#' || *p == ';' || *p == '\0') 16955682Smarkm continue; 17055682Smarkm while(isspace((unsigned char)*p)) 17155682Smarkm ++p; 17255682Smarkm if (*p == '}') 17355682Smarkm return 0; 17455682Smarkm if (*p == '\0') 17555682Smarkm continue; 176233294Sstas ret = parse_binding (f, lineno, p, &b, parent, err_message); 17755682Smarkm if (ret) 17855682Smarkm return ret; 17955682Smarkm } 18055682Smarkm *lineno = beg_lineno; 181233294Sstas *err_message = "unclosed {"; 18278527Sassar return KRB5_CONFIG_BADFORMAT; 18355682Smarkm} 18455682Smarkm 18555682Smarkm/* 18655682Smarkm * 18755682Smarkm */ 18855682Smarkm 189127808Snectarstatic krb5_error_code 190178825Sdfrparse_binding(struct fileptr *f, unsigned *lineno, char *p, 19155682Smarkm krb5_config_binding **b, krb5_config_binding **parent, 192233294Sstas const char **err_message) 19355682Smarkm{ 19455682Smarkm krb5_config_binding *tmp; 19555682Smarkm char *p1, *p2; 196127808Snectar krb5_error_code ret = 0; 19755682Smarkm 19855682Smarkm p1 = p; 19955682Smarkm while (*p && *p != '=' && !isspace((unsigned char)*p)) 20055682Smarkm ++p; 20155682Smarkm if (*p == '\0') { 202233294Sstas *err_message = "missing ="; 20378527Sassar return KRB5_CONFIG_BADFORMAT; 20455682Smarkm } 20555682Smarkm p2 = p; 20655682Smarkm while (isspace((unsigned char)*p)) 20755682Smarkm ++p; 20855682Smarkm if (*p != '=') { 209233294Sstas *err_message = "missing ="; 21078527Sassar return KRB5_CONFIG_BADFORMAT; 21155682Smarkm } 21255682Smarkm ++p; 21355682Smarkm while(isspace((unsigned char)*p)) 21455682Smarkm ++p; 21555682Smarkm *p2 = '\0'; 21655682Smarkm if (*p == '{') { 217233294Sstas tmp = _krb5_config_get_entry(parent, p1, krb5_config_list); 218102644Snectar if (tmp == NULL) { 219233294Sstas *err_message = "out of memory"; 220102644Snectar return KRB5_CONFIG_BADFORMAT; 221102644Snectar } 222233294Sstas ret = parse_list (f, lineno, &tmp->u.list, err_message); 22355682Smarkm } else { 224233294Sstas tmp = _krb5_config_get_entry(parent, p1, krb5_config_string); 225102644Snectar if (tmp == NULL) { 226233294Sstas *err_message = "out of memory"; 227102644Snectar return KRB5_CONFIG_BADFORMAT; 228102644Snectar } 22955682Smarkm p1 = p; 23055682Smarkm p = p1 + strlen(p1); 23155682Smarkm while(p > p1 && isspace((unsigned char)*(p-1))) 23255682Smarkm --p; 23355682Smarkm *p = '\0'; 23455682Smarkm tmp->u.string = strdup(p1); 23555682Smarkm } 23655682Smarkm *b = tmp; 23755682Smarkm return ret; 23855682Smarkm} 23955682Smarkm 240233294Sstas#if defined(__APPLE__) 241233294Sstas 242233294Sstas#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 243233294Sstas#define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1 244233294Sstas#endif 245233294Sstas 246233294Sstasstatic char * 247233294Sstascfstring2cstring(CFStringRef string) 248233294Sstas{ 249233294Sstas CFIndex len; 250233294Sstas char *str; 251233294Sstas 252233294Sstas str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8); 253233294Sstas if (str) 254233294Sstas return strdup(str); 255233294Sstas 256233294Sstas len = CFStringGetLength(string); 257233294Sstas len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8); 258233294Sstas str = malloc(len); 259233294Sstas if (str == NULL) 260233294Sstas return NULL; 261233294Sstas 262233294Sstas if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) { 263233294Sstas free (str); 264233294Sstas return NULL; 265233294Sstas } 266233294Sstas return str; 267233294Sstas} 268233294Sstas 269233294Sstasstatic void 270233294Sstasconvert_content(const void *key, const void *value, void *context) 271233294Sstas{ 272233294Sstas krb5_config_section *tmp, **parent = context; 273233294Sstas char *k; 274233294Sstas 275233294Sstas if (CFGetTypeID(key) != CFStringGetTypeID()) 276233294Sstas return; 277233294Sstas 278233294Sstas k = cfstring2cstring(key); 279233294Sstas if (k == NULL) 280233294Sstas return; 281233294Sstas 282233294Sstas if (CFGetTypeID(value) == CFStringGetTypeID()) { 283233294Sstas tmp = _krb5_config_get_entry(parent, k, krb5_config_string); 284233294Sstas tmp->u.string = cfstring2cstring(value); 285233294Sstas } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { 286233294Sstas tmp = _krb5_config_get_entry(parent, k, krb5_config_list); 287233294Sstas CFDictionaryApplyFunction(value, convert_content, &tmp->u.list); 288233294Sstas } else { 289233294Sstas /* log */ 290233294Sstas } 291233294Sstas free(k); 292233294Sstas} 293233294Sstas 294233294Sstasstatic krb5_error_code 295233294Sstasparse_plist_config(krb5_context context, const char *path, krb5_config_section **parent) 296233294Sstas{ 297233294Sstas CFReadStreamRef s; 298233294Sstas CFDictionaryRef d; 299233294Sstas CFURLRef url; 300233294Sstas 301233294Sstas url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), FALSE); 302233294Sstas if (url == NULL) { 303233294Sstas krb5_clear_error_message(context); 304233294Sstas return ENOMEM; 305233294Sstas } 306233294Sstas 307233294Sstas s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url); 308233294Sstas CFRelease(url); 309233294Sstas if (s == NULL) { 310233294Sstas krb5_clear_error_message(context); 311233294Sstas return ENOMEM; 312233294Sstas } 313233294Sstas 314233294Sstas if (!CFReadStreamOpen(s)) { 315233294Sstas CFRelease(s); 316233294Sstas krb5_clear_error_message(context); 317233294Sstas return ENOENT; 318233294Sstas } 319233294Sstas 320233294Sstas#ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM 321233294Sstas d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL); 322233294Sstas#else 323233294Sstas d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL); 324233294Sstas#endif 325233294Sstas CFRelease(s); 326233294Sstas if (d == NULL) { 327233294Sstas krb5_clear_error_message(context); 328233294Sstas return ENOENT; 329233294Sstas } 330233294Sstas 331233294Sstas CFDictionaryApplyFunction(d, convert_content, parent); 332233294Sstas CFRelease(d); 333233294Sstas 334233294Sstas return 0; 335233294Sstas} 336233294Sstas 337233294Sstas#endif 338233294Sstas 339233294Sstas 34055682Smarkm/* 34155682Smarkm * Parse the config file `fname', generating the structures into `res' 342233294Sstas * returning error messages in `err_message' 34355682Smarkm */ 34455682Smarkm 34578527Sassarstatic krb5_error_code 346178825Sdfrkrb5_config_parse_debug (struct fileptr *f, 347178825Sdfr krb5_config_section **res, 348178825Sdfr unsigned *lineno, 349233294Sstas const char **err_message) 35055682Smarkm{ 351178825Sdfr krb5_config_section *s = NULL; 352178825Sdfr krb5_config_binding *b = NULL; 353233294Sstas char buf[KRB5_BUFSIZ]; 354178825Sdfr krb5_error_code ret; 35555682Smarkm 356178825Sdfr while (config_fgets(buf, sizeof(buf), f) != NULL) { 35755682Smarkm char *p; 35855682Smarkm 35955682Smarkm ++*lineno; 360178825Sdfr buf[strcspn(buf, "\r\n")] = '\0'; 36155682Smarkm p = buf; 36255682Smarkm while(isspace((unsigned char)*p)) 36355682Smarkm ++p; 36455682Smarkm if (*p == '#' || *p == ';') 36555682Smarkm continue; 36655682Smarkm if (*p == '[') { 367233294Sstas ret = parse_section(p, &s, res, err_message); 368233294Sstas if (ret) 369178825Sdfr return ret; 37055682Smarkm b = NULL; 37155682Smarkm } else if (*p == '}') { 372233294Sstas *err_message = "unmatched }"; 373178825Sdfr return EINVAL; /* XXX */ 37455682Smarkm } else if(*p != '\0') { 375127808Snectar if (s == NULL) { 376233294Sstas *err_message = "binding before section"; 377178825Sdfr return EINVAL; 378127808Snectar } 379233294Sstas ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message); 38055682Smarkm if (ret) 381178825Sdfr return ret; 38255682Smarkm } 38355682Smarkm } 384178825Sdfr return 0; 38555682Smarkm} 38655682Smarkm 387233294Sstasstatic int 388233294Sstasis_plist_file(const char *fname) 389178825Sdfr{ 390233294Sstas size_t len = strlen(fname); 391233294Sstas char suffix[] = ".plist"; 392233294Sstas if (len < sizeof(suffix)) 393233294Sstas return 0; 394233294Sstas if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0) 395233294Sstas return 0; 396233294Sstas return 1; 397178825Sdfr} 398178825Sdfr 399233294Sstas/** 400233294Sstas * Parse a configuration file and add the result into res. This 401233294Sstas * interface can be used to parse several configuration files into one 402233294Sstas * resulting krb5_config_section by calling it repeatably. 403233294Sstas * 404233294Sstas * @param context a Kerberos 5 context. 405233294Sstas * @param fname a file name to a Kerberos configuration file 406233294Sstas * @param res the returned result, must be free with krb5_free_config_files(). 407233294Sstas * @return Return an error code or 0, see krb5_get_error_message(). 408233294Sstas * 409233294Sstas * @ingroup krb5_support 410233294Sstas */ 411233294Sstas 412233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 413102644Snectarkrb5_config_parse_file_multi (krb5_context context, 414102644Snectar const char *fname, 415102644Snectar krb5_config_section **res) 41655682Smarkm{ 417102644Snectar const char *str; 418233294Sstas char *newfname = NULL; 419178825Sdfr unsigned lineno = 0; 42078527Sassar krb5_error_code ret; 421178825Sdfr struct fileptr f; 422233294Sstas 423233294Sstas /** 424233294Sstas * If the fname starts with "~/" parse configuration file in the 425233294Sstas * current users home directory. The behavior can be disabled and 426233294Sstas * enabled by calling krb5_set_home_dir_access(). 427233294Sstas */ 428233294Sstas if (fname[0] == '~' && fname[1] == '/') { 429233294Sstas#ifndef KRB5_USE_PATH_TOKENS 430233294Sstas const char *home = NULL; 431233294Sstas 432233294Sstas if (!_krb5_homedir_access(context)) { 433233294Sstas krb5_set_error_message(context, EPERM, 434233294Sstas "Access to home directory not allowed"); 435233294Sstas return EPERM; 436233294Sstas } 437233294Sstas 438233294Sstas if(!issuid()) 439233294Sstas home = getenv("HOME"); 440233294Sstas 441233294Sstas if (home == NULL) { 442233294Sstas struct passwd *pw = getpwuid(getuid()); 443233294Sstas if(pw != NULL) 444233294Sstas home = pw->pw_dir; 445233294Sstas } 446233294Sstas if (home) { 447233294Sstas asprintf(&newfname, "%s%s", home, &fname[1]); 448233294Sstas if (newfname == NULL) { 449233294Sstas krb5_set_error_message(context, ENOMEM, 450233294Sstas N_("malloc: out of memory", "")); 451233294Sstas return ENOMEM; 452233294Sstas } 453233294Sstas fname = newfname; 454233294Sstas } 455233294Sstas#else /* KRB5_USE_PATH_TOKENS */ 456233294Sstas if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 || 457233294Sstas newfname == NULL) 458233294Sstas { 459233294Sstas krb5_set_error_message(context, ENOMEM, 460233294Sstas N_("malloc: out of memory", "")); 461233294Sstas return ENOMEM; 462233294Sstas } 463233294Sstas fname = newfname; 464233294Sstas#endif 465178825Sdfr } 46655682Smarkm 467233294Sstas if (is_plist_file(fname)) { 468233294Sstas#ifdef __APPLE__ 469233294Sstas ret = parse_plist_config(context, fname, res); 470233294Sstas if (ret) { 471233294Sstas krb5_set_error_message(context, ret, 472233294Sstas "Failed to parse plist %s", fname); 473233294Sstas if (newfname) 474233294Sstas free(newfname); 475233294Sstas return ret; 476233294Sstas } 477233294Sstas#else 478233294Sstas krb5_set_error_message(context, ENOENT, 479233294Sstas "no support for plist configuration files"); 480233294Sstas return ENOENT; 481233294Sstas#endif 482233294Sstas } else { 483233294Sstas#ifdef KRB5_USE_PATH_TOKENS 484233294Sstas char * exp_fname = NULL; 485233294Sstas 486233294Sstas ret = _krb5_expand_path_tokens(context, fname, &exp_fname); 487233294Sstas if (ret) { 488233294Sstas if (newfname) 489233294Sstas free(newfname); 490233294Sstas return ret; 491233294Sstas } 492233294Sstas 493233294Sstas if (newfname) 494233294Sstas free(newfname); 495233294Sstas fname = newfname = exp_fname; 496233294Sstas#endif 497233294Sstas 498233294Sstas f.f = fopen(fname, "r"); 499233294Sstas f.s = NULL; 500233294Sstas if(f.f == NULL) { 501233294Sstas ret = errno; 502233294Sstas krb5_set_error_message (context, ret, "open %s: %s", 503233294Sstas fname, strerror(ret)); 504233294Sstas if (newfname) 505233294Sstas free(newfname); 506233294Sstas return ret; 507233294Sstas } 508233294Sstas 509233294Sstas ret = krb5_config_parse_debug (&f, res, &lineno, &str); 510233294Sstas fclose(f.f); 511233294Sstas if (ret) { 512233294Sstas krb5_set_error_message (context, ret, "%s:%u: %s", 513233294Sstas fname, lineno, str); 514233294Sstas if (newfname) 515233294Sstas free(newfname); 516233294Sstas return ret; 517233294Sstas } 51878527Sassar } 51978527Sassar return 0; 52055682Smarkm} 52155682Smarkm 522233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 523102644Snectarkrb5_config_parse_file (krb5_context context, 524102644Snectar const char *fname, 525102644Snectar krb5_config_section **res) 526102644Snectar{ 527102644Snectar *res = NULL; 528102644Snectar return krb5_config_parse_file_multi(context, fname, res); 529102644Snectar} 530102644Snectar 53155682Smarkmstatic void 53255682Smarkmfree_binding (krb5_context context, krb5_config_binding *b) 53355682Smarkm{ 53455682Smarkm krb5_config_binding *next_b; 53555682Smarkm 53655682Smarkm while (b) { 53755682Smarkm free (b->name); 53855682Smarkm if (b->type == krb5_config_string) 53955682Smarkm free (b->u.string); 54055682Smarkm else if (b->type == krb5_config_list) 54155682Smarkm free_binding (context, b->u.list); 54255682Smarkm else 543233294Sstas krb5_abortx(context, "unknown binding type (%d) in free_binding", 54455682Smarkm b->type); 54555682Smarkm next_b = b->next; 54655682Smarkm free (b); 54755682Smarkm b = next_b; 54855682Smarkm } 54955682Smarkm} 55055682Smarkm 551233294Sstas/** 552233294Sstas * Free configuration file section, the result of 553233294Sstas * krb5_config_parse_file() and krb5_config_parse_file_multi(). 554233294Sstas * 555233294Sstas * @param context A Kerberos 5 context 556233294Sstas * @param s the configuration section to free 557233294Sstas * 558233294Sstas * @return returns 0 on successes, otherwise an error code, see 559233294Sstas * krb5_get_error_message() 560233294Sstas * 561233294Sstas * @ingroup krb5_support 562233294Sstas */ 563233294Sstas 564233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 56555682Smarkmkrb5_config_file_free (krb5_context context, krb5_config_section *s) 56655682Smarkm{ 56755682Smarkm free_binding (context, s); 56855682Smarkm return 0; 56955682Smarkm} 57055682Smarkm 571233294Sstas#ifndef HEIMDAL_SMALLER 572233294Sstas 573233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 574233294Sstas_krb5_config_copy(krb5_context context, 575233294Sstas krb5_config_section *c, 576233294Sstas krb5_config_section **head) 57755682Smarkm{ 578233294Sstas krb5_config_binding *d, *previous = NULL; 579233294Sstas 580233294Sstas *head = NULL; 581233294Sstas 582233294Sstas while (c) { 583233294Sstas d = calloc(1, sizeof(*d)); 584233294Sstas 585233294Sstas if (*head == NULL) 586233294Sstas *head = d; 587233294Sstas 588233294Sstas d->name = strdup(c->name); 589233294Sstas d->type = c->type; 590233294Sstas if (d->type == krb5_config_string) 591233294Sstas d->u.string = strdup(c->u.string); 592233294Sstas else if (d->type == krb5_config_list) 593233294Sstas _krb5_config_copy (context, c->u.list, &d->u.list); 594233294Sstas else 595233294Sstas krb5_abortx(context, 596233294Sstas "unknown binding type (%d) in krb5_config_copy", 597233294Sstas d->type); 598233294Sstas if (previous) 599233294Sstas previous->next = d; 600233294Sstas 601233294Sstas previous = d; 602233294Sstas c = c->next; 603233294Sstas } 604233294Sstas return 0; 605233294Sstas} 606233294Sstas 607233294Sstas#endif /* HEIMDAL_SMALLER */ 608233294Sstas 609233294SstasKRB5_LIB_FUNCTION const void * KRB5_LIB_CALL 610233294Sstas_krb5_config_get_next (krb5_context context, 611233294Sstas const krb5_config_section *c, 612233294Sstas const krb5_config_binding **pointer, 613233294Sstas int type, 614233294Sstas ...) 615233294Sstas{ 61655682Smarkm const char *ret; 61755682Smarkm va_list args; 61855682Smarkm 61955682Smarkm va_start(args, type); 620233294Sstas ret = _krb5_config_vget_next (context, c, pointer, type, args); 62155682Smarkm va_end(args); 62255682Smarkm return ret; 62355682Smarkm} 62455682Smarkm 625102644Snectarstatic const void * 626102644Snectarvget_next(krb5_context context, 627102644Snectar const krb5_config_binding *b, 628102644Snectar const krb5_config_binding **pointer, 629102644Snectar int type, 630102644Snectar const char *name, 631102644Snectar va_list args) 632102644Snectar{ 633102644Snectar const char *p = va_arg(args, const char *); 634102644Snectar while(b != NULL) { 635103423Snectar if(strcmp(b->name, name) == 0) { 636233294Sstas if(b->type == (unsigned)type && p == NULL) { 637102644Snectar *pointer = b; 638102644Snectar return b->u.generic; 639102644Snectar } else if(b->type == krb5_config_list && p != NULL) { 640102644Snectar return vget_next(context, b->u.list, pointer, type, p, args); 641102644Snectar } 642102644Snectar } 643102644Snectar b = b->next; 644102644Snectar } 645102644Snectar return NULL; 646102644Snectar} 647102644Snectar 648233294SstasKRB5_LIB_FUNCTION const void * KRB5_LIB_CALL 649233294Sstas_krb5_config_vget_next (krb5_context context, 650233294Sstas const krb5_config_section *c, 651233294Sstas const krb5_config_binding **pointer, 652233294Sstas int type, 653233294Sstas va_list args) 65455682Smarkm{ 655102644Snectar const krb5_config_binding *b; 65655682Smarkm const char *p; 65755682Smarkm 65855682Smarkm if(c == NULL) 65955682Smarkm c = context->cf; 66055682Smarkm 66155682Smarkm if (c == NULL) 66255682Smarkm return NULL; 66355682Smarkm 66455682Smarkm if (*pointer == NULL) { 665102644Snectar /* first time here, walk down the tree looking for the right 666102644Snectar section */ 66755682Smarkm p = va_arg(args, const char *); 66855682Smarkm if (p == NULL) 66955682Smarkm return NULL; 670102644Snectar return vget_next(context, c, pointer, type, p, args); 67155682Smarkm } 67255682Smarkm 673102644Snectar /* we were called again, so just look for more entries with the 674102644Snectar same name and type */ 675102644Snectar for (b = (*pointer)->next; b != NULL; b = b->next) { 676233294Sstas if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) { 677102644Snectar *pointer = b; 678102644Snectar return b->u.generic; 67955682Smarkm } 68055682Smarkm } 68155682Smarkm return NULL; 68255682Smarkm} 68355682Smarkm 684233294SstasKRB5_LIB_FUNCTION const void * KRB5_LIB_CALL 685233294Sstas_krb5_config_get (krb5_context context, 686233294Sstas const krb5_config_section *c, 687233294Sstas int type, 688233294Sstas ...) 68955682Smarkm{ 69055682Smarkm const void *ret; 69155682Smarkm va_list args; 69255682Smarkm 69355682Smarkm va_start(args, type); 694233294Sstas ret = _krb5_config_vget (context, c, type, args); 69555682Smarkm va_end(args); 69655682Smarkm return ret; 69755682Smarkm} 69855682Smarkm 699233294Sstas 70055682Smarkmconst void * 701233294Sstas_krb5_config_vget (krb5_context context, 702233294Sstas const krb5_config_section *c, 703233294Sstas int type, 704233294Sstas va_list args) 70555682Smarkm{ 706102644Snectar const krb5_config_binding *foo = NULL; 70755682Smarkm 708233294Sstas return _krb5_config_vget_next (context, c, &foo, type, args); 70955682Smarkm} 71055682Smarkm 711233294Sstas/** 712233294Sstas * Get a list of configuration binding list for more processing 713233294Sstas * 714233294Sstas * @param context A Kerberos 5 context. 715233294Sstas * @param c a configuration section, or NULL to use the section from context 716233294Sstas * @param ... a list of names, terminated with NULL. 717233294Sstas * 718233294Sstas * @return NULL if configuration list is not found, a list otherwise 719233294Sstas * 720233294Sstas * @ingroup krb5_support 721233294Sstas */ 722233294Sstas 723233294SstasKRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL 72455682Smarkmkrb5_config_get_list (krb5_context context, 725102644Snectar const krb5_config_section *c, 72655682Smarkm ...) 72755682Smarkm{ 72855682Smarkm const krb5_config_binding *ret; 72955682Smarkm va_list args; 73055682Smarkm 73155682Smarkm va_start(args, c); 73255682Smarkm ret = krb5_config_vget_list (context, c, args); 73355682Smarkm va_end(args); 73455682Smarkm return ret; 73555682Smarkm} 73655682Smarkm 737233294Sstas/** 738233294Sstas * Get a list of configuration binding list for more processing 739233294Sstas * 740233294Sstas * @param context A Kerberos 5 context. 741233294Sstas * @param c a configuration section, or NULL to use the section from context 742233294Sstas * @param args a va_list of arguments 743233294Sstas * 744233294Sstas * @return NULL if configuration list is not found, a list otherwise 745233294Sstas * 746233294Sstas * @ingroup krb5_support 747233294Sstas */ 748233294Sstas 749233294SstasKRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL 75055682Smarkmkrb5_config_vget_list (krb5_context context, 751102644Snectar const krb5_config_section *c, 75255682Smarkm va_list args) 75355682Smarkm{ 754233294Sstas return _krb5_config_vget (context, c, krb5_config_list, args); 75555682Smarkm} 75655682Smarkm 757233294Sstas/** 758233294Sstas * Returns a "const char *" to a string in the configuration database. 759233294Sstas * The string may not be valid after a reload of the configuration 760233294Sstas * database so a caller should make a local copy if it needs to keep 761233294Sstas * the string. 762233294Sstas * 763233294Sstas * @param context A Kerberos 5 context. 764233294Sstas * @param c a configuration section, or NULL to use the section from context 765233294Sstas * @param ... a list of names, terminated with NULL. 766233294Sstas * 767233294Sstas * @return NULL if configuration string not found, a string otherwise 768233294Sstas * 769233294Sstas * @ingroup krb5_support 770233294Sstas */ 771233294Sstas 772233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 77355682Smarkmkrb5_config_get_string (krb5_context context, 774102644Snectar const krb5_config_section *c, 77555682Smarkm ...) 77655682Smarkm{ 77755682Smarkm const char *ret; 77855682Smarkm va_list args; 77955682Smarkm 78055682Smarkm va_start(args, c); 78155682Smarkm ret = krb5_config_vget_string (context, c, args); 78255682Smarkm va_end(args); 78355682Smarkm return ret; 78455682Smarkm} 78555682Smarkm 786233294Sstas/** 787233294Sstas * Like krb5_config_get_string(), but uses a va_list instead of ... 788233294Sstas * 789233294Sstas * @param context A Kerberos 5 context. 790233294Sstas * @param c a configuration section, or NULL to use the section from context 791233294Sstas * @param args a va_list of arguments 792233294Sstas * 793233294Sstas * @return NULL if configuration string not found, a string otherwise 794233294Sstas * 795233294Sstas * @ingroup krb5_support 796233294Sstas */ 797233294Sstas 798233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 79955682Smarkmkrb5_config_vget_string (krb5_context context, 800102644Snectar const krb5_config_section *c, 80155682Smarkm va_list args) 80255682Smarkm{ 803233294Sstas return _krb5_config_vget (context, c, krb5_config_string, args); 80455682Smarkm} 80555682Smarkm 806233294Sstas/** 807233294Sstas * Like krb5_config_vget_string(), but instead of returning NULL, 808233294Sstas * instead return a default value. 809233294Sstas * 810233294Sstas * @param context A Kerberos 5 context. 811233294Sstas * @param c a configuration section, or NULL to use the section from context 812233294Sstas * @param def_value the default value to return if no configuration 813233294Sstas * found in the database. 814233294Sstas * @param args a va_list of arguments 815233294Sstas * 816233294Sstas * @return a configuration string 817233294Sstas * 818233294Sstas * @ingroup krb5_support 819233294Sstas */ 820233294Sstas 821233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 82272445Sassarkrb5_config_vget_string_default (krb5_context context, 823102644Snectar const krb5_config_section *c, 82472445Sassar const char *def_value, 82572445Sassar va_list args) 82672445Sassar{ 82772445Sassar const char *ret; 82872445Sassar 82972445Sassar ret = krb5_config_vget_string (context, c, args); 83072445Sassar if (ret == NULL) 83172445Sassar ret = def_value; 83272445Sassar return ret; 83372445Sassar} 83472445Sassar 835233294Sstas/** 836233294Sstas * Like krb5_config_get_string(), but instead of returning NULL, 837233294Sstas * instead return a default value. 838233294Sstas * 839233294Sstas * @param context A Kerberos 5 context. 840233294Sstas * @param c a configuration section, or NULL to use the section from context 841233294Sstas * @param def_value the default value to return if no configuration 842233294Sstas * found in the database. 843233294Sstas * @param ... a list of names, terminated with NULL. 844233294Sstas * 845233294Sstas * @return a configuration string 846233294Sstas * 847233294Sstas * @ingroup krb5_support 848233294Sstas */ 849233294Sstas 850233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL 85172445Sassarkrb5_config_get_string_default (krb5_context context, 852102644Snectar const krb5_config_section *c, 85372445Sassar const char *def_value, 85472445Sassar ...) 85572445Sassar{ 85672445Sassar const char *ret; 85772445Sassar va_list args; 85872445Sassar 85972445Sassar va_start(args, def_value); 86072445Sassar ret = krb5_config_vget_string_default (context, c, def_value, args); 86172445Sassar va_end(args); 86272445Sassar return ret; 86372445Sassar} 86472445Sassar 865233294Sstasstatic char * 866233294Sstasnext_component_string(char * begin, const char * delims, char **state) 867233294Sstas{ 868233294Sstas char * end; 869233294Sstas 870233294Sstas if (begin == NULL) 871233294Sstas begin = *state; 872233294Sstas 873233294Sstas if (*begin == '\0') 874233294Sstas return NULL; 875233294Sstas 876233294Sstas end = begin; 877233294Sstas while (*end == '"') { 878233294Sstas char * t = strchr(end + 1, '"'); 879233294Sstas 880233294Sstas if (t) 881233294Sstas end = ++t; 882233294Sstas else 883233294Sstas end += strlen(end); 884233294Sstas } 885233294Sstas 886233294Sstas if (*end != '\0') { 887233294Sstas size_t pos; 888233294Sstas 889233294Sstas pos = strcspn(end, delims); 890233294Sstas end = end + pos; 891233294Sstas } 892233294Sstas 893233294Sstas if (*end != '\0') { 894233294Sstas *end = '\0'; 895233294Sstas *state = end + 1; 896233294Sstas if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) { 897233294Sstas begin++; *(end - 1) = '\0'; 898233294Sstas } 899233294Sstas return begin; 900233294Sstas } 901233294Sstas 902233294Sstas *state = end; 903233294Sstas if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) { 904233294Sstas begin++; *(end - 1) = '\0'; 905233294Sstas } 906233294Sstas return begin; 907233294Sstas} 908233294Sstas 909233294Sstas/** 910233294Sstas * Get a list of configuration strings, free the result with 911233294Sstas * krb5_config_free_strings(). 912233294Sstas * 913233294Sstas * @param context A Kerberos 5 context. 914233294Sstas * @param c a configuration section, or NULL to use the section from context 915233294Sstas * @param args a va_list of arguments 916233294Sstas * 917233294Sstas * @return TRUE or FALSE 918233294Sstas * 919233294Sstas * @ingroup krb5_support 920233294Sstas */ 921233294Sstas 922233294SstasKRB5_LIB_FUNCTION char ** KRB5_LIB_CALL 92355682Smarkmkrb5_config_vget_strings(krb5_context context, 924102644Snectar const krb5_config_section *c, 92555682Smarkm va_list args) 92655682Smarkm{ 92755682Smarkm char **strings = NULL; 92855682Smarkm int nstr = 0; 929102644Snectar const krb5_config_binding *b = NULL; 93055682Smarkm const char *p; 93155682Smarkm 932233294Sstas while((p = _krb5_config_vget_next(context, c, &b, 933233294Sstas krb5_config_string, args))) { 93455682Smarkm char *tmp = strdup(p); 93555682Smarkm char *pos = NULL; 93655682Smarkm char *s; 93755682Smarkm if(tmp == NULL) 93855682Smarkm goto cleanup; 939233294Sstas s = next_component_string(tmp, " \t", &pos); 94055682Smarkm while(s){ 941178825Sdfr char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings)); 942178825Sdfr if(tmp2 == NULL) 94355682Smarkm goto cleanup; 944178825Sdfr strings = tmp2; 94555682Smarkm strings[nstr] = strdup(s); 94655682Smarkm nstr++; 94755682Smarkm if(strings[nstr-1] == NULL) 94855682Smarkm goto cleanup; 949233294Sstas s = next_component_string(NULL, " \t", &pos); 95055682Smarkm } 95155682Smarkm free(tmp); 95255682Smarkm } 95355682Smarkm if(nstr){ 95455682Smarkm char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings)); 955178825Sdfr if(tmp == NULL) 95655682Smarkm goto cleanup; 95755682Smarkm strings = tmp; 95855682Smarkm strings[nstr] = NULL; 95955682Smarkm } 96055682Smarkm return strings; 96155682Smarkmcleanup: 96255682Smarkm while(nstr--) 96355682Smarkm free(strings[nstr]); 96455682Smarkm free(strings); 96555682Smarkm return NULL; 96655682Smarkm 96755682Smarkm} 96855682Smarkm 969233294Sstas/** 970233294Sstas * Get a list of configuration strings, free the result with 971233294Sstas * krb5_config_free_strings(). 972233294Sstas * 973233294Sstas * @param context A Kerberos 5 context. 974233294Sstas * @param c a configuration section, or NULL to use the section from context 975233294Sstas * @param ... a list of names, terminated with NULL. 976233294Sstas * 977233294Sstas * @return TRUE or FALSE 978233294Sstas * 979233294Sstas * @ingroup krb5_support 980233294Sstas */ 981233294Sstas 982233294SstasKRB5_LIB_FUNCTION char** KRB5_LIB_CALL 98355682Smarkmkrb5_config_get_strings(krb5_context context, 984102644Snectar const krb5_config_section *c, 98555682Smarkm ...) 98655682Smarkm{ 98755682Smarkm va_list ap; 98855682Smarkm char **ret; 98955682Smarkm va_start(ap, c); 99055682Smarkm ret = krb5_config_vget_strings(context, c, ap); 99155682Smarkm va_end(ap); 99255682Smarkm return ret; 99355682Smarkm} 99455682Smarkm 995233294Sstas/** 996233294Sstas * Free the resulting strings from krb5_config-get_strings() and 997233294Sstas * krb5_config_vget_strings(). 998233294Sstas * 999233294Sstas * @param strings strings to free 1000233294Sstas * 1001233294Sstas * @ingroup krb5_support 1002233294Sstas */ 1003233294Sstas 1004233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 100555682Smarkmkrb5_config_free_strings(char **strings) 100655682Smarkm{ 100755682Smarkm char **s = strings; 100855682Smarkm while(s && *s){ 100955682Smarkm free(*s); 101055682Smarkm s++; 101155682Smarkm } 101255682Smarkm free(strings); 101355682Smarkm} 101455682Smarkm 1015233294Sstas/** 1016233294Sstas * Like krb5_config_get_bool_default() but with a va_list list of 1017233294Sstas * configuration selection. 1018233294Sstas * 1019233294Sstas * Configuration value to a boolean value, where yes/true and any 1020233294Sstas * non-zero number means TRUE and other value is FALSE. 1021233294Sstas * 1022233294Sstas * @param context A Kerberos 5 context. 1023233294Sstas * @param c a configuration section, or NULL to use the section from context 1024233294Sstas * @param def_value the default value to return if no configuration 1025233294Sstas * found in the database. 1026233294Sstas * @param args a va_list of arguments 1027233294Sstas * 1028233294Sstas * @return TRUE or FALSE 1029233294Sstas * 1030233294Sstas * @ingroup krb5_support 1031233294Sstas */ 1032233294Sstas 1033233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 103455682Smarkmkrb5_config_vget_bool_default (krb5_context context, 1035102644Snectar const krb5_config_section *c, 103655682Smarkm krb5_boolean def_value, 103755682Smarkm va_list args) 103855682Smarkm{ 103955682Smarkm const char *str; 104055682Smarkm str = krb5_config_vget_string (context, c, args); 104155682Smarkm if(str == NULL) 104255682Smarkm return def_value; 104355682Smarkm if(strcasecmp(str, "yes") == 0 || 104455682Smarkm strcasecmp(str, "true") == 0 || 104555682Smarkm atoi(str)) return TRUE; 104655682Smarkm return FALSE; 104755682Smarkm} 104855682Smarkm 1049233294Sstas/** 1050233294Sstas * krb5_config_get_bool() will convert the configuration 1051233294Sstas * option value to a boolean value, where yes/true and any non-zero 1052233294Sstas * number means TRUE and other value is FALSE. 1053233294Sstas * 1054233294Sstas * @param context A Kerberos 5 context. 1055233294Sstas * @param c a configuration section, or NULL to use the section from context 1056233294Sstas * @param args a va_list of arguments 1057233294Sstas * 1058233294Sstas * @return TRUE or FALSE 1059233294Sstas * 1060233294Sstas * @ingroup krb5_support 1061233294Sstas */ 1062233294Sstas 1063233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 106455682Smarkmkrb5_config_vget_bool (krb5_context context, 1065102644Snectar const krb5_config_section *c, 106655682Smarkm va_list args) 106755682Smarkm{ 106855682Smarkm return krb5_config_vget_bool_default (context, c, FALSE, args); 106955682Smarkm} 107055682Smarkm 1071233294Sstas/** 1072233294Sstas * krb5_config_get_bool_default() will convert the configuration 1073233294Sstas * option value to a boolean value, where yes/true and any non-zero 1074233294Sstas * number means TRUE and other value is FALSE. 1075233294Sstas * 1076233294Sstas * @param context A Kerberos 5 context. 1077233294Sstas * @param c a configuration section, or NULL to use the section from context 1078233294Sstas * @param def_value the default value to return if no configuration 1079233294Sstas * found in the database. 1080233294Sstas * @param ... a list of names, terminated with NULL. 1081233294Sstas * 1082233294Sstas * @return TRUE or FALSE 1083233294Sstas * 1084233294Sstas * @ingroup krb5_support 1085233294Sstas */ 1086233294Sstas 1087233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 108855682Smarkmkrb5_config_get_bool_default (krb5_context context, 1089102644Snectar const krb5_config_section *c, 109055682Smarkm krb5_boolean def_value, 109155682Smarkm ...) 109255682Smarkm{ 109355682Smarkm va_list ap; 109455682Smarkm krb5_boolean ret; 109555682Smarkm va_start(ap, def_value); 109655682Smarkm ret = krb5_config_vget_bool_default(context, c, def_value, ap); 109755682Smarkm va_end(ap); 109855682Smarkm return ret; 109955682Smarkm} 110055682Smarkm 1101233294Sstas/** 1102233294Sstas * Like krb5_config_get_bool() but with a va_list list of 1103233294Sstas * configuration selection. 1104233294Sstas * 1105233294Sstas * Configuration value to a boolean value, where yes/true and any 1106233294Sstas * non-zero number means TRUE and other value is FALSE. 1107233294Sstas * 1108233294Sstas * @param context A Kerberos 5 context. 1109233294Sstas * @param c a configuration section, or NULL to use the section from context 1110233294Sstas * @param ... a list of names, terminated with NULL. 1111233294Sstas * 1112233294Sstas * @return TRUE or FALSE 1113233294Sstas * 1114233294Sstas * @ingroup krb5_support 1115233294Sstas */ 1116233294Sstas 1117233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 111855682Smarkmkrb5_config_get_bool (krb5_context context, 1119102644Snectar const krb5_config_section *c, 112055682Smarkm ...) 112155682Smarkm{ 112255682Smarkm va_list ap; 112355682Smarkm krb5_boolean ret; 112455682Smarkm va_start(ap, c); 112555682Smarkm ret = krb5_config_vget_bool (context, c, ap); 112655682Smarkm va_end(ap); 112755682Smarkm return ret; 112855682Smarkm} 112955682Smarkm 1130233294Sstas/** 1131233294Sstas * Get the time from the configuration file using a relative time. 1132233294Sstas * 1133233294Sstas * Like krb5_config_get_time_default() but with a va_list list of 1134233294Sstas * configuration selection. 1135233294Sstas * 1136233294Sstas * @param context A Kerberos 5 context. 1137233294Sstas * @param c a configuration section, or NULL to use the section from context 1138233294Sstas * @param def_value the default value to return if no configuration 1139233294Sstas * found in the database. 1140233294Sstas * @param args a va_list of arguments 1141233294Sstas * 1142233294Sstas * @return parsed the time (or def_value on parse error) 1143233294Sstas * 1144233294Sstas * @ingroup krb5_support 1145233294Sstas */ 1146233294Sstas 1147233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 114855682Smarkmkrb5_config_vget_time_default (krb5_context context, 1149102644Snectar const krb5_config_section *c, 115055682Smarkm int def_value, 115155682Smarkm va_list args) 115255682Smarkm{ 115355682Smarkm const char *str; 1154178825Sdfr krb5_deltat t; 1155178825Sdfr 115655682Smarkm str = krb5_config_vget_string (context, c, args); 115755682Smarkm if(str == NULL) 115855682Smarkm return def_value; 1159178825Sdfr if (krb5_string_to_deltat(str, &t)) 1160178825Sdfr return def_value; 1161178825Sdfr return t; 116255682Smarkm} 116355682Smarkm 1164233294Sstas/** 1165233294Sstas * Get the time from the configuration file using a relative time, for example: 1h30s 1166233294Sstas * 1167233294Sstas * @param context A Kerberos 5 context. 1168233294Sstas * @param c a configuration section, or NULL to use the section from context 1169233294Sstas * @param args a va_list of arguments 1170233294Sstas * 1171233294Sstas * @return parsed the time or -1 on error 1172233294Sstas * 1173233294Sstas * @ingroup krb5_support 1174233294Sstas */ 1175233294Sstas 1176233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 117755682Smarkmkrb5_config_vget_time (krb5_context context, 1178102644Snectar const krb5_config_section *c, 117955682Smarkm va_list args) 118055682Smarkm{ 118155682Smarkm return krb5_config_vget_time_default (context, c, -1, args); 118255682Smarkm} 118355682Smarkm 1184233294Sstas/** 1185233294Sstas * Get the time from the configuration file using a relative time, for example: 1h30s 1186233294Sstas * 1187233294Sstas * @param context A Kerberos 5 context. 1188233294Sstas * @param c a configuration section, or NULL to use the section from context 1189233294Sstas * @param def_value the default value to return if no configuration 1190233294Sstas * found in the database. 1191233294Sstas * @param ... a list of names, terminated with NULL. 1192233294Sstas * 1193233294Sstas * @return parsed the time (or def_value on parse error) 1194233294Sstas * 1195233294Sstas * @ingroup krb5_support 1196233294Sstas */ 1197233294Sstas 1198233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 119955682Smarkmkrb5_config_get_time_default (krb5_context context, 1200102644Snectar const krb5_config_section *c, 120155682Smarkm int def_value, 120255682Smarkm ...) 120355682Smarkm{ 120455682Smarkm va_list ap; 120555682Smarkm int ret; 120655682Smarkm va_start(ap, def_value); 120755682Smarkm ret = krb5_config_vget_time_default(context, c, def_value, ap); 120855682Smarkm va_end(ap); 120955682Smarkm return ret; 121055682Smarkm} 121155682Smarkm 1212233294Sstas/** 1213233294Sstas * Get the time from the configuration file using a relative time, for example: 1h30s 1214233294Sstas * 1215233294Sstas * @param context A Kerberos 5 context. 1216233294Sstas * @param c a configuration section, or NULL to use the section from context 1217233294Sstas * @param ... a list of names, terminated with NULL. 1218233294Sstas * 1219233294Sstas * @return parsed the time or -1 on error 1220233294Sstas * 1221233294Sstas * @ingroup krb5_support 1222233294Sstas */ 1223233294Sstas 1224233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 122555682Smarkmkrb5_config_get_time (krb5_context context, 1226102644Snectar const krb5_config_section *c, 122755682Smarkm ...) 122855682Smarkm{ 122955682Smarkm va_list ap; 123055682Smarkm int ret; 123155682Smarkm va_start(ap, c); 123255682Smarkm ret = krb5_config_vget_time (context, c, ap); 123355682Smarkm va_end(ap); 123455682Smarkm return ret; 123555682Smarkm} 123655682Smarkm 123755682Smarkm 1238233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 123955682Smarkmkrb5_config_vget_int_default (krb5_context context, 1240102644Snectar const krb5_config_section *c, 124155682Smarkm int def_value, 124255682Smarkm va_list args) 124355682Smarkm{ 124455682Smarkm const char *str; 124555682Smarkm str = krb5_config_vget_string (context, c, args); 124655682Smarkm if(str == NULL) 124755682Smarkm return def_value; 1248233294Sstas else { 1249233294Sstas char *endptr; 1250233294Sstas long l; 1251233294Sstas l = strtol(str, &endptr, 0); 1252233294Sstas if (endptr == str) 1253233294Sstas return def_value; 1254233294Sstas else 125555682Smarkm return l; 125655682Smarkm } 125755682Smarkm} 125855682Smarkm 1259233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 126055682Smarkmkrb5_config_vget_int (krb5_context context, 1261102644Snectar const krb5_config_section *c, 126255682Smarkm va_list args) 126355682Smarkm{ 126455682Smarkm return krb5_config_vget_int_default (context, c, -1, args); 126555682Smarkm} 126655682Smarkm 1267233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 126855682Smarkmkrb5_config_get_int_default (krb5_context context, 1269102644Snectar const krb5_config_section *c, 127055682Smarkm int def_value, 127155682Smarkm ...) 127255682Smarkm{ 127355682Smarkm va_list ap; 127455682Smarkm int ret; 127555682Smarkm va_start(ap, def_value); 127655682Smarkm ret = krb5_config_vget_int_default(context, c, def_value, ap); 127755682Smarkm va_end(ap); 127855682Smarkm return ret; 127955682Smarkm} 128055682Smarkm 1281233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 128255682Smarkmkrb5_config_get_int (krb5_context context, 1283102644Snectar const krb5_config_section *c, 128455682Smarkm ...) 128555682Smarkm{ 128655682Smarkm va_list ap; 128755682Smarkm int ret; 128855682Smarkm va_start(ap, c); 128955682Smarkm ret = krb5_config_vget_int (context, c, ap); 129055682Smarkm va_end(ap); 129155682Smarkm return ret; 129255682Smarkm} 1293233294Sstas 1294233294Sstas 1295233294Sstas#ifndef HEIMDAL_SMALLER 1296233294Sstas 1297233294Sstas/** 1298233294Sstas * Deprecated: configuration files are not strings 1299233294Sstas * 1300233294Sstas * @ingroup krb5_deprecated 1301233294Sstas */ 1302233294Sstas 1303233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1304233294Sstaskrb5_config_parse_string_multi(krb5_context context, 1305233294Sstas const char *string, 1306233294Sstas krb5_config_section **res) 1307233294Sstas KRB5_DEPRECATED_FUNCTION("Use X instead") 1308233294Sstas{ 1309233294Sstas const char *str; 1310233294Sstas unsigned lineno = 0; 1311233294Sstas krb5_error_code ret; 1312233294Sstas struct fileptr f; 1313233294Sstas f.f = NULL; 1314233294Sstas f.s = string; 1315233294Sstas 1316233294Sstas ret = krb5_config_parse_debug (&f, res, &lineno, &str); 1317233294Sstas if (ret) { 1318233294Sstas krb5_set_error_message (context, ret, "%s:%u: %s", 1319233294Sstas "<constant>", lineno, str); 1320233294Sstas return ret; 1321233294Sstas } 1322233294Sstas return 0; 1323233294Sstas} 1324233294Sstas 1325233294Sstas#endif 1326