s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / source4 / heimdal / lib / krb5 / config_file.c
1 /*
2  * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include "krb5_locl.h"
37
38 #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
39 #include <CoreFoundation/CoreFoundation.h>
40 #endif
41
42 /**
43  * Parse configuration files in the given directory and add the result
44  * into res.  Only files whose names consist only of alphanumeric
45  * characters, hyphen, and underscore, will be parsed, though files
46  * ending in ".conf" will also be parsed.
47  *
48  * This interface can be used to parse several configuration directories
49  * into one resulting krb5_config_section by calling it repeatably.
50  *
51  * @param context a Kerberos 5 context.
52  * @param dname a directory name to a Kerberos configuration file
53  * @param res the returned result, must be free with krb5_free_config_files().
54  * @return Return an error code or 0, see krb5_get_error_message().
55  *
56  * @ingroup krb5_support
57  */
58
59 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
60 krb5_config_parse_dir_multi(krb5_context context,
61                             const char *dname,
62                             krb5_config_section **res)
63 {
64     krb5_error_code ret;
65     heim_config_section *section = NULL;
66
67     if (res == NULL)
68         return EINVAL;
69
70     *res = NULL;
71
72     ret = heim_config_parse_dir_multi(context->hcontext, dname, &section);
73     if (ret == HEIM_ERR_CONFIG_BADFORMAT)
74         return KRB5_CONFIG_BADFORMAT;
75     if (ret)
76         return ret;
77     *res = (krb5_config_section *)section;
78     return 0;
79 }
80
81 /**
82  * Parse a configuration file and add the result into res. This
83  * interface can be used to parse several configuration files into one
84  * resulting krb5_config_section by calling it repeatably.
85  *
86  * @param context a Kerberos 5 context.
87  * @param fname a file name to a Kerberos configuration file
88  * @param res the returned result, must be free with krb5_free_config_files().
89  * @return Return an error code or 0, see krb5_get_error_message().
90  *
91  * @ingroup krb5_support
92  */
93
94 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
95 krb5_config_parse_file_multi(krb5_context context,
96                              const char *fname,
97                              krb5_config_section **res)
98 {
99     krb5_error_code ret;
100     heim_config_section *section = NULL;
101
102     if (res == NULL)
103         return EINVAL;
104
105     *res = NULL;
106
107     ret = heim_config_parse_file_multi(context->hcontext, fname, &section);
108     if (ret == HEIM_ERR_CONFIG_BADFORMAT)
109         return KRB5_CONFIG_BADFORMAT;
110     if (ret)
111         return ret;
112     *res = (krb5_config_section *)section;
113     return 0;
114 }
115
116 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
117 krb5_config_parse_file(krb5_context context,
118                        const char *fname,
119                        krb5_config_section **res)
120 {
121     return krb5_config_parse_file_multi(context, fname, res);
122 }
123
124 /**
125  * Free configuration file section, the result of
126  * krb5_config_parse_file() and krb5_config_parse_file_multi().
127  *
128  * @param context A Kerberos 5 context
129  * @param s the configuration section to free
130  *
131  * @return returns 0 on successes, otherwise an error code, see
132  *          krb5_get_error_message()
133  *
134  * @ingroup krb5_support
135  */
136
137 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
138 krb5_config_file_free(krb5_context context, krb5_config_section *s)
139 {
140     return heim_config_file_free(context->hcontext, (heim_config_section *)s);
141 }
142
143 #ifndef HEIMDAL_SMALLER
144
145 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
146 _krb5_config_copy(krb5_context context,
147                   krb5_config_section *c,
148                   krb5_config_section **res)
149 {
150     krb5_error_code ret;
151     heim_config_section *section = NULL;
152
153     if (res == NULL)
154         return EINVAL;
155
156     *res = NULL;
157     ret = heim_config_copy(context->hcontext, (heim_config_section *)c, &section);
158     if (ret)
159         return ret;
160     *res = (krb5_config_section *)section;
161     return 0;
162 }
163
164 #endif /* HEIMDAL_SMALLER */
165
166 KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
167 _krb5_config_get_next(krb5_context context,
168                       const krb5_config_section *c,
169                       const krb5_config_binding **pointer,
170                       int type,
171                       ...)
172 {
173     const char *ret;
174     va_list args;
175
176     va_start(args, type);
177     ret = heim_config_vget_next(context->hcontext,
178                                 (const heim_config_section *)(c ? c : context->cf),
179                                 (const heim_config_binding **)pointer, type, args);
180     va_end(args);
181     return ret;
182 }
183
184 KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
185 _krb5_config_vget_next(krb5_context context,
186                        const krb5_config_section *c,
187                        const krb5_config_binding **pointer,
188                        int type,
189                        va_list args)
190 {
191     return heim_config_vget_next(context->hcontext,
192                                  (const heim_config_section *)(c ? c : context->cf),
193                                  (const heim_config_binding **)pointer, type, args);
194 }
195
196 KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
197 _krb5_config_get(krb5_context context,
198                  const krb5_config_section *c,
199                  int type,
200                  ...)
201 {
202     const void *ret;
203     va_list args;
204
205     va_start(args, type);
206     ret = heim_config_vget(context->hcontext,
207                            (const heim_config_section *)(c ? c : context->cf),
208                            type, args);
209     va_end(args);
210     return ret;
211 }
212
213
214 KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
215 _krb5_config_vget(krb5_context context,
216                   const krb5_config_section *c,
217                   int type,
218                   va_list args)
219 {
220     return heim_config_vget(context->hcontext,
221                             (const heim_config_section *)(c ? c : context->cf),
222                             type, args);
223 }
224
225 /**
226  * Get a list of configuration binding list for more processing
227  *
228  * @param context A Kerberos 5 context.
229  * @param c a configuration section, or NULL to use the section from context
230  * @param ... a list of names, terminated with NULL.
231  *
232  * @return NULL if configuration list is not found, a list otherwise
233  *
234  * @ingroup krb5_support
235  */
236
237 KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL
238 krb5_config_get_list(krb5_context context,
239                      const krb5_config_section *c,
240                      ...)
241 {
242     const heim_config_binding *ret;
243     va_list args;
244
245     va_start(args, c);
246     ret = heim_config_vget_list(context->hcontext,
247                                 (const heim_config_section *)(c ? c : context->cf),
248                                 args);
249     va_end(args);
250     return (const krb5_config_binding *)ret;
251 }
252
253 /**
254  * Get a list of configuration binding list for more processing
255  *
256  * @param context A Kerberos 5 context.
257  * @param c a configuration section, or NULL to use the section from context
258  * @param args a va_list of arguments
259  *
260  * @return NULL if configuration list is not found, a list otherwise
261  *
262  * @ingroup krb5_support
263  */
264
265 KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL
266 krb5_config_vget_list(krb5_context context,
267                       const krb5_config_section *c,
268                       va_list args)
269 {
270     const heim_config_binding *ret;
271
272     ret = heim_config_vget_list(context->hcontext,
273                                 (const heim_config_section *)(c ? c : context->cf),
274                                 args);
275     return (const krb5_config_binding *)ret;
276 }
277
278 /**
279  * Returns a "const char *" to a string in the configuration database.
280  * The string may not be valid after a reload of the configuration
281  * database so a caller should make a local copy if it needs to keep
282  * the string.
283  *
284  * @param context A Kerberos 5 context.
285  * @param c a configuration section, or NULL to use the section from context
286  * @param ... a list of names, terminated with NULL.
287  *
288  * @return NULL if configuration string not found, a string otherwise
289  *
290  * @ingroup krb5_support
291  */
292
293 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
294 krb5_config_get_string(krb5_context context,
295                        const krb5_config_section *c,
296                        ...)
297 {
298     const char *ret;
299     va_list args;
300
301     va_start(args, c);
302     ret = heim_config_vget_string(context->hcontext,
303                                   (const heim_config_section *)(c ? c : context->cf),
304                                   args);
305     va_end(args);
306     return ret;
307 }
308
309 /**
310  * Like krb5_config_get_string(), but uses a va_list instead of ...
311  *
312  * @param context A Kerberos 5 context.
313  * @param c a configuration section, or NULL to use the section from context
314  * @param args a va_list of arguments
315  *
316  * @return NULL if configuration string not found, a string otherwise
317  *
318  * @ingroup krb5_support
319  */
320
321 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
322 krb5_config_vget_string(krb5_context context,
323                         const krb5_config_section *c,
324                         va_list args)
325 {
326     return heim_config_vget_string(context->hcontext,
327                                    (const heim_config_section *)(c ? c : context->cf),
328                                    args);
329 }
330
331 /**
332  * Like krb5_config_vget_string(), but instead of returning NULL,
333  * instead return a default value.
334  *
335  * @param context A Kerberos 5 context.
336  * @param c a configuration section, or NULL to use the section from context
337  * @param def_value the default value to return if no configuration
338  *        found in the database.
339  * @param args a va_list of arguments
340  *
341  * @return a configuration string
342  *
343  * @ingroup krb5_support
344  */
345
346 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
347 krb5_config_vget_string_default(krb5_context context,
348                                 const krb5_config_section *c,
349                                 const char *def_value,
350                                 va_list args)
351 {
352     return heim_config_vget_string_default(context->hcontext,
353                                            (const heim_config_section *)(c ? c : context->cf),
354                                            def_value, args);
355 }
356
357 /**
358  * Like krb5_config_get_string(), but instead of returning NULL,
359  * instead return a default value.
360  *
361  * @param context A Kerberos 5 context.
362  * @param c a configuration section, or NULL to use the section from context
363  * @param def_value the default value to return if no configuration
364  *        found in the database.
365  * @param ... a list of names, terminated with NULL.
366  *
367  * @return a configuration string
368  *
369  * @ingroup krb5_support
370  */
371
372 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
373 krb5_config_get_string_default(krb5_context context,
374                                const krb5_config_section *c,
375                                const char *def_value,
376                                ...)
377 {
378     const char *ret;
379     va_list args;
380
381     va_start(args, def_value);
382     ret = heim_config_vget_string_default(context->hcontext,
383                                           (const heim_config_section *)(c ? c : context->cf),
384                                           def_value, args);
385     va_end(args);
386     return ret;
387 }
388
389 /**
390  * Get a list of configuration strings, free the result with
391  * krb5_config_free_strings().
392  *
393  * @param context A Kerberos 5 context.
394  * @param c a configuration section, or NULL to use the section from context
395  * @param args a va_list of arguments
396  *
397  * @return TRUE or FALSE
398  *
399  * @ingroup krb5_support
400  */
401
402 KRB5_LIB_FUNCTION char ** KRB5_LIB_CALL
403 krb5_config_vget_strings(krb5_context context,
404                          const krb5_config_section *c,
405                          va_list args)
406 {
407     return heim_config_vget_strings(context->hcontext,
408                                     (const heim_config_section *)(c ? c : context->cf),
409                                     args);
410 }
411
412 /**
413  * Get a list of configuration strings, free the result with
414  * krb5_config_free_strings().
415  *
416  * @param context A Kerberos 5 context.
417  * @param c a configuration section, or NULL to use the section from context
418  * @param ... a list of names, terminated with NULL.
419  *
420  * @return TRUE or FALSE
421  *
422  * @ingroup krb5_support
423  */
424
425 KRB5_LIB_FUNCTION char** KRB5_LIB_CALL
426 krb5_config_get_strings(krb5_context context,
427                         const krb5_config_section *c,
428                         ...)
429 {
430     va_list ap;
431     char **ret;
432     va_start(ap, c);
433     ret = heim_config_vget_strings(context->hcontext,
434                                    (const heim_config_section *)(c ? c : context->cf),
435                                    ap);
436     va_end(ap);
437     return ret;
438 }
439
440 /**
441  * Free the resulting strings from krb5_config-get_strings() and
442  * krb5_config_vget_strings().
443  *
444  * @param strings strings to free
445  *
446  * @ingroup krb5_support
447  */
448
449 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
450 krb5_config_free_strings(char **strings)
451 {
452     heim_config_free_strings(strings);
453 }
454
455 /**
456  * Like krb5_config_get_bool_default() but with a va_list list of
457  * configuration selection.
458  *
459  * Configuration value to a boolean value, where yes/true and any
460  * non-zero number means TRUE and other value is FALSE.
461  *
462  * @param context A Kerberos 5 context.
463  * @param c a configuration section, or NULL to use the section from context
464  * @param def_value the default value to return if no configuration
465  *        found in the database.
466  * @param args a va_list of arguments
467  *
468  * @return TRUE or FALSE
469  *
470  * @ingroup krb5_support
471  */
472
473 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
474 krb5_config_vget_bool_default(krb5_context context,
475                               const krb5_config_section *c,
476                               krb5_boolean def_value,
477                               va_list args)
478 {
479     return heim_config_vget_bool_default(context->hcontext,
480                                          (const heim_config_section *)(c ? c : context->cf),
481                                          def_value, args);
482 }
483
484 /**
485  * krb5_config_get_bool() will convert the configuration
486  * option value to a boolean value, where yes/true and any non-zero
487  * number means TRUE and other value is FALSE.
488  *
489  * @param context A Kerberos 5 context.
490  * @param c a configuration section, or NULL to use the section from context
491  * @param args a va_list of arguments
492  *
493  * @return TRUE or FALSE
494  *
495  * @ingroup krb5_support
496  */
497
498 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
499 krb5_config_vget_bool(krb5_context context,
500                       const krb5_config_section *c,
501                       va_list args)
502 {
503     return heim_config_vget_bool_default(context->hcontext,
504                                          (const heim_config_section *)(c ? c : context->cf),
505                                          FALSE, args);
506 }
507
508 /**
509  * krb5_config_get_bool_default() will convert the configuration
510  * option value to a boolean value, where yes/true and any non-zero
511  * number means TRUE and other value is FALSE.
512  *
513  * @param context A Kerberos 5 context.
514  * @param c a configuration section, or NULL to use the section from context
515  * @param def_value the default value to return if no configuration
516  *        found in the database.
517  * @param ... a list of names, terminated with NULL.
518  *
519  * @return TRUE or FALSE
520  *
521  * @ingroup krb5_support
522  */
523
524 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
525 krb5_config_get_bool_default(krb5_context context,
526                              const krb5_config_section *c,
527                              krb5_boolean def_value,
528                              ...)
529 {
530     va_list ap;
531     krb5_boolean ret;
532     va_start(ap, def_value);
533     ret = heim_config_vget_bool_default(context->hcontext,
534                                         (const heim_config_section *)(c ? c : context->cf),
535                                         def_value, ap);
536     va_end(ap);
537     return ret;
538 }
539
540 /**
541  * Like krb5_config_get_bool() but with a va_list list of
542  * configuration selection.
543  *
544  * Configuration value to a boolean value, where yes/true and any
545  * non-zero number means TRUE and other value is FALSE.
546  *
547  * @param context A Kerberos 5 context.
548  * @param c a configuration section, or NULL to use the section from context
549  * @param ... a list of names, terminated with NULL.
550  *
551  * @return TRUE or FALSE
552  *
553  * @ingroup krb5_support
554  */
555
556 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
557 krb5_config_get_bool (krb5_context context,
558                       const krb5_config_section *c,
559                       ...)
560 {
561     va_list ap;
562     krb5_boolean ret;
563     va_start(ap, c);
564     ret = krb5_config_vget_bool (context, c, ap);
565     va_end(ap);
566     return ret;
567 }
568
569 /**
570  * Get the time from the configuration file using a relative time.
571  *
572  * Like krb5_config_get_time_default() but with a va_list list of
573  * configuration selection.
574  *
575  * @param context A Kerberos 5 context.
576  * @param c a configuration section, or NULL to use the section from context
577  * @param def_value the default value to return if no configuration
578  *        found in the database.
579  * @param args a va_list of arguments
580  *
581  * @return parsed the time (or def_value on parse error)
582  *
583  * @ingroup krb5_support
584  */
585
586 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
587 krb5_config_vget_time_default(krb5_context context,
588                               const krb5_config_section *c,
589                               int def_value,
590                               va_list args)
591 {
592     return heim_config_vget_time_default(context->hcontext,
593                                          (const heim_config_section *)(c ? c : context->cf),
594                                          def_value, args);
595 }
596
597 /**
598  * Get the time from the configuration file using a relative time, for example: 1h30s
599  *
600  * @param context A Kerberos 5 context.
601  * @param c a configuration section, or NULL to use the section from context
602  * @param args a va_list of arguments
603  *
604  * @return parsed the time or -1 on error
605  *
606  * @ingroup krb5_support
607  */
608
609 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
610 krb5_config_vget_time(krb5_context context,
611                       const krb5_config_section *c,
612                       va_list args)
613 {
614     return heim_config_vget_time_default(context->hcontext,
615                                          (const heim_config_section *)(c ? c : context->cf),
616                                          -1, args);
617 }
618
619 /**
620  * Get the time from the configuration file using a relative time, for example: 1h30s
621  *
622  * @param context A Kerberos 5 context.
623  * @param c a configuration section, or NULL to use the section from context
624  * @param def_value the default value to return if no configuration
625  *        found in the database.
626  * @param ... a list of names, terminated with NULL.
627  *
628  * @return parsed the time (or def_value on parse error)
629  *
630  * @ingroup krb5_support
631  */
632
633 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
634 krb5_config_get_time_default(krb5_context context,
635                              const krb5_config_section *c,
636                              int def_value,
637                              ...)
638 {
639     va_list ap;
640     int ret;
641     va_start(ap, def_value);
642     ret = heim_config_vget_time_default(context->hcontext,
643                                         (const heim_config_section *)(c ? c : context->cf),
644                                         def_value, ap);
645     va_end(ap);
646     return ret;
647 }
648
649 /**
650  * Get the time from the configuration file using a relative time, for example: 1h30s
651  *
652  * @param context A Kerberos 5 context.
653  * @param c a configuration section, or NULL to use the section from context
654  * @param ... a list of names, terminated with NULL.
655  *
656  * @return parsed the time or -1 on error
657  *
658  * @ingroup krb5_support
659  */
660
661 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
662 krb5_config_get_time(krb5_context context,
663                      const krb5_config_section *c,
664                      ...)
665 {
666     va_list ap;
667     int ret;
668     va_start(ap, c);
669     ret = heim_config_vget_time(context->hcontext,
670                                 (const heim_config_section *)(c ? c : context->cf),
671                                 ap);
672     va_end(ap);
673     return ret;
674 }
675
676
677 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
678 krb5_config_vget_int_default(krb5_context context,
679                              const krb5_config_section *c,
680                              int def_value,
681                              va_list args)
682 {
683     return heim_config_vget_int_default(context->hcontext,
684                                         (const heim_config_section *)(c ? c : context->cf),
685                                         def_value, args);
686 }
687
688 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
689 krb5_config_vget_int(krb5_context context,
690                      const krb5_config_section *c,
691                      va_list args)
692 {
693     return heim_config_vget_int_default(context->hcontext,
694                                         (const heim_config_section *)(c ? c : context->cf),
695                                         -1, args);
696 }
697
698 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
699 krb5_config_get_int_default(krb5_context context,
700                             const krb5_config_section *c,
701                             int def_value,
702                             ...)
703 {
704     va_list ap;
705     int ret;
706     va_start(ap, def_value);
707     ret = heim_config_vget_int_default(context->hcontext,
708                                        (const heim_config_section *)(c ? c : context->cf),
709                                        def_value, ap);
710     va_end(ap);
711     return ret;
712 }
713
714 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
715 krb5_config_get_int(krb5_context context,
716                     const krb5_config_section *c,
717                     ...)
718 {
719     va_list ap;
720     int ret;
721     va_start(ap, c);
722     ret = heim_config_vget_int(context->hcontext,
723                                (const heim_config_section *)(c ? c : context->cf),
724                                ap);
725     va_end(ap);
726     return ret;
727 }
728
729
730 #ifndef HEIMDAL_SMALLER
731 /**
732  * Deprecated: configuration files are not strings
733  *
734  * @ingroup krb5_deprecated
735  */
736
737 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
738 krb5_config_parse_string_multi(krb5_context context,
739                                const char *string,
740                                krb5_config_section **res)
741     KRB5_DEPRECATED_FUNCTION("Use X instead")
742 {
743     krb5_error_code ret;
744     heim_config_section *section = NULL;
745
746     if (res == NULL)
747         return EINVAL;
748
749     *res = NULL;
750     ret = heim_config_parse_string_multi(context->hcontext, string, &section);
751     if (ret == HEIM_ERR_CONFIG_BADFORMAT)
752         return KRB5_CONFIG_BADFORMAT;
753     if (ret)
754         return ret;
755     *res = (krb5_config_section *)section;
756     return 0;
757 }
758 #endif