1 /* conf_lib.c */
   2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
   3  * project 2000.
   4  */
   5 /* ====================================================================
   6  * Copyright (c) 2000 The OpenSSL Project.  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
  17  *    the documentation and/or other materials provided with the
  18  *    distribution.
  19  *
  20  * 3. All advertising materials mentioning features or use of this
  21  *    software must display the following acknowledgment:
  22  *    "This product includes software developed by the OpenSSL Project
  23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24  *
  25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26  *    endorse or promote products derived from this software without
  27  *    prior written permission. For written permission, please contact
  28  *    licensing@OpenSSL.org.
  29  *
  30  * 5. Products derived from this software may not be called "OpenSSL"
  31  *    nor may "OpenSSL" appear in their names without prior written
  32  *    permission of the OpenSSL Project.
  33  *
  34  * 6. Redistributions of any form whatsoever must retain the following
  35  *    acknowledgment:
  36  *    "This product includes software developed by the OpenSSL Project
  37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38  *
  39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50  * OF THE POSSIBILITY OF SUCH DAMAGE.
  51  * ====================================================================
  52  *
  53  * This product includes cryptographic software written by Eric Young
  54  * (eay@cryptsoft.com).  This product includes software written by Tim
  55  * Hudson (tjh@cryptsoft.com).
  56  *
  57  */
  58 
  59 #include <stdio.h>
  60 #include <openssl/crypto.h>
  61 #include <openssl/err.h>
  62 #include <openssl/conf.h>
  63 #include <openssl/conf_api.h>
  64 #include <openssl/lhash.h>
  65 
  66 const char CONF_version[]="CONF" OPENSSL_VERSION_PTEXT;
  67 
  68 static CONF_METHOD *default_CONF_method=NULL;
  69 
  70 /* Init a 'CONF' structure from an old LHASH */
  71 
  72 void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash)
  73         {
  74         if (default_CONF_method == NULL)
  75                 default_CONF_method = NCONF_default();
  76 
  77         default_CONF_method->init(conf);
  78         conf->data = hash;
  79         }
  80 
  81 /* The following section contains the "CONF classic" functions,
  82    rewritten in terms of the new CONF interface. */
  83 
  84 int CONF_set_default_method(CONF_METHOD *meth)
  85         {
  86         default_CONF_method = meth;
  87         return 1;
  88         }
  89 
  90 LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
  91                                 long *eline)
  92         {
  93         LHASH_OF(CONF_VALUE) *ltmp;
  94         BIO *in=NULL;
  95 
  96 #ifdef OPENSSL_SYS_VMS
  97         in=BIO_new_file(file, "r");
  98 #else
  99         in=BIO_new_file(file, "rb");
 100 #endif
 101         if (in == NULL)
 102                 {
 103                 CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB);
 104                 return NULL;
 105                 }
 106 
 107         ltmp = CONF_load_bio(conf, in, eline);
 108         BIO_free(in);
 109 
 110         return ltmp;
 111         }
 112 
 113 #ifndef OPENSSL_NO_FP_API
 114 LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
 115                                    long *eline)
 116         {
 117         BIO *btmp;
 118         LHASH_OF(CONF_VALUE) *ltmp;
 119         if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) {
 120                 CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB);
 121                 return NULL;
 122         }
 123         ltmp = CONF_load_bio(conf, btmp, eline);
 124         BIO_free(btmp);
 125         return ltmp;
 126         }
 127 #endif
 128 
 129 LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
 130                                     long *eline)
 131         {
 132         CONF ctmp;
 133         int ret;
 134 
 135         CONF_set_nconf(&ctmp, conf);
 136 
 137         ret = NCONF_load_bio(&ctmp, bp, eline);
 138         if (ret)
 139                 return ctmp.data;
 140         return NULL;
 141         }
 142 
 143 STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
 144                                        const char *section)
 145         {
 146         if (conf == NULL)
 147                 {
 148                 return NULL;
 149                 }
 150         else
 151                 {
 152                 CONF ctmp;
 153                 CONF_set_nconf(&ctmp, conf);
 154                 return NCONF_get_section(&ctmp, section);
 155                 }
 156         }
 157 
 158 char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf,const char *group,
 159                       const char *name)
 160         {
 161         if (conf == NULL)
 162                 {
 163                 return NCONF_get_string(NULL, group, name);
 164                 }
 165         else
 166                 {
 167                 CONF ctmp;
 168                 CONF_set_nconf(&ctmp, conf);
 169                 return NCONF_get_string(&ctmp, group, name);
 170                 }
 171         }
 172 
 173 long CONF_get_number(LHASH_OF(CONF_VALUE) *conf,const char *group,
 174                      const char *name)
 175         {
 176         int status;
 177         long result = 0;
 178 
 179         if (conf == NULL)
 180                 {
 181                 status = NCONF_get_number_e(NULL, group, name, &result);
 182                 }
 183         else
 184                 {
 185                 CONF ctmp;
 186                 CONF_set_nconf(&ctmp, conf);
 187                 status = NCONF_get_number_e(&ctmp, group, name, &result);
 188                 }
 189 
 190         if (status == 0)
 191                 {
 192                 /* This function does not believe in errors... */
 193                 ERR_clear_error();
 194                 }
 195         return result;
 196         }
 197 
 198 void CONF_free(LHASH_OF(CONF_VALUE) *conf)
 199         {
 200         CONF ctmp;
 201         CONF_set_nconf(&ctmp, conf);
 202         NCONF_free_data(&ctmp);
 203         }
 204 
 205 #ifndef OPENSSL_NO_FP_API
 206 int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out)
 207         {
 208         BIO *btmp;
 209         int ret;
 210 
 211         if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
 212                 CONFerr(CONF_F_CONF_DUMP_FP,ERR_R_BUF_LIB);
 213                 return 0;
 214         }
 215         ret = CONF_dump_bio(conf, btmp);
 216         BIO_free(btmp);
 217         return ret;
 218         }
 219 #endif
 220 
 221 int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
 222         {
 223         CONF ctmp;
 224         CONF_set_nconf(&ctmp, conf);
 225         return NCONF_dump_bio(&ctmp, out);
 226         }
 227 
 228 /* The following section contains the "New CONF" functions.  They are
 229    completely centralised around a new CONF structure that may contain
 230    basically anything, but at least a method pointer and a table of data.
 231    These functions are also written in terms of the bridge functions used
 232    by the "CONF classic" functions, for consistency.  */
 233 
 234 CONF *NCONF_new(CONF_METHOD *meth)
 235         {
 236         CONF *ret;
 237 
 238         if (meth == NULL)
 239                 meth = NCONF_default();
 240 
 241         ret = meth->create(meth);
 242         if (ret == NULL)
 243                 {
 244                 CONFerr(CONF_F_NCONF_NEW,ERR_R_MALLOC_FAILURE);
 245                 return(NULL);
 246                 }
 247 
 248         return ret;
 249         }
 250 
 251 void NCONF_free(CONF *conf)
 252         {
 253         if (conf == NULL)
 254                 return;
 255         conf->meth->destroy(conf);
 256         }
 257 
 258 void NCONF_free_data(CONF *conf)
 259         {
 260         if (conf == NULL)
 261                 return;
 262         conf->meth->destroy_data(conf);
 263         }
 264 
 265 int NCONF_load(CONF *conf, const char *file, long *eline)
 266         {
 267         if (conf == NULL)
 268                 {
 269                 CONFerr(CONF_F_NCONF_LOAD,CONF_R_NO_CONF);
 270                 return 0;
 271                 }
 272 
 273         return conf->meth->load(conf, file, eline);
 274         }
 275 
 276 #ifndef OPENSSL_NO_FP_API
 277 int NCONF_load_fp(CONF *conf, FILE *fp,long *eline)
 278         {
 279         BIO *btmp;
 280         int ret;
 281         if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE)))
 282                 {
 283                 CONFerr(CONF_F_NCONF_LOAD_FP,ERR_R_BUF_LIB);
 284                 return 0;
 285                 }
 286         ret = NCONF_load_bio(conf, btmp, eline);
 287         BIO_free(btmp);
 288         return ret;
 289         }
 290 #endif
 291 
 292 int NCONF_load_bio(CONF *conf, BIO *bp,long *eline)
 293         {
 294         if (conf == NULL)
 295                 {
 296                 CONFerr(CONF_F_NCONF_LOAD_BIO,CONF_R_NO_CONF);
 297                 return 0;
 298                 }
 299 
 300         return conf->meth->load_bio(conf, bp, eline);
 301         }
 302 
 303 STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,const char *section)
 304         {
 305         if (conf == NULL)
 306                 {
 307                 CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_CONF);
 308                 return NULL;
 309                 }
 310 
 311         if (section == NULL)
 312                 {
 313                 CONFerr(CONF_F_NCONF_GET_SECTION,CONF_R_NO_SECTION);
 314                 return NULL;
 315                 }
 316 
 317         return _CONF_get_section_values(conf, section);
 318         }
 319 
 320 char *NCONF_get_string(const CONF *conf,const char *group,const char *name)
 321         {
 322         char *s = _CONF_get_string(conf, group, name);
 323 
 324         /* Since we may get a value from an environment variable even
 325            if conf is NULL, let's check the value first */
 326         if (s) return s;
 327 
 328         if (conf == NULL)
 329                 {
 330                 CONFerr(CONF_F_NCONF_GET_STRING,
 331                         CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE);
 332                 return NULL;
 333                 }
 334         CONFerr(CONF_F_NCONF_GET_STRING,
 335                 CONF_R_NO_VALUE);
 336         ERR_add_error_data(4,"group=",group," name=",name);
 337         return NULL;
 338         }
 339 
 340 int NCONF_get_number_e(const CONF *conf,const char *group,const char *name,
 341                        long *result)
 342         {
 343         char *str;
 344 
 345         if (result == NULL)
 346                 {
 347                 CONFerr(CONF_F_NCONF_GET_NUMBER_E,ERR_R_PASSED_NULL_PARAMETER);
 348                 return 0;
 349                 }
 350 
 351         str = NCONF_get_string(conf,group,name);
 352 
 353         if (str == NULL)
 354                 return 0;
 355 
 356         for (*result = 0;conf->meth->is_number(conf, *str);)
 357                 {
 358                 *result = (*result)*10 + conf->meth->to_int(conf, *str);
 359                 str++;
 360                 }
 361 
 362         return 1;
 363         }
 364 
 365 #ifndef OPENSSL_NO_FP_API
 366 int NCONF_dump_fp(const CONF *conf, FILE *out)
 367         {
 368         BIO *btmp;
 369         int ret;
 370         if(!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
 371                 CONFerr(CONF_F_NCONF_DUMP_FP,ERR_R_BUF_LIB);
 372                 return 0;
 373         }
 374         ret = NCONF_dump_bio(conf, btmp);
 375         BIO_free(btmp);
 376         return ret;
 377         }
 378 #endif
 379 
 380 int NCONF_dump_bio(const CONF *conf, BIO *out)
 381         {
 382         if (conf == NULL)
 383                 {
 384                 CONFerr(CONF_F_NCONF_DUMP_BIO,CONF_R_NO_CONF);
 385                 return 0;
 386                 }
 387 
 388         return conf->meth->dump(conf, out);
 389         }
 390 
 391 
 392 /* This function should be avoided */
 393 #if 0
 394 long NCONF_get_number(CONF *conf,char *group,char *name)
 395         {
 396         int status;
 397         long ret=0;
 398 
 399         status = NCONF_get_number_e(conf, group, name, &ret);
 400         if (status == 0)
 401                 {
 402                 /* This function does not believe in errors... */
 403                 ERR_get_error();
 404                 }
 405         return ret;
 406         }
 407 #endif