1 /* conf_mod.c */
   2 /* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
   3  * project 2001.
   4  */
   5 /* ====================================================================
   6  * Copyright (c) 2001 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 <ctype.h>
  61 #include <openssl/crypto.h>
  62 #include "cryptlib.h"
  63 #include <openssl/conf.h>
  64 #include <openssl/dso.h>
  65 #include <openssl/x509.h>
  66 
  67 
  68 #define DSO_mod_init_name "OPENSSL_init"
  69 #define DSO_mod_finish_name "OPENSSL_finish"
  70 
  71 
  72 /* This structure contains a data about supported modules.
  73  * entries in this table correspond to either dynamic or
  74  * static modules.
  75  */
  76 
  77 struct conf_module_st
  78         {
  79         /* DSO of this module or NULL if static */
  80         DSO *dso;
  81         /* Name of the module */
  82         char *name;
  83         /* Init function */
  84         conf_init_func *init;
  85         /* Finish function */
  86         conf_finish_func *finish;
  87         /* Number of successfully initialized modules */
  88         int links;
  89         void *usr_data;
  90         };
  91 
  92 
  93 /* This structure contains information about modules that have been
  94  * successfully initialized. There may be more than one entry for a
  95  * given module.
  96  */
  97 
  98 struct conf_imodule_st
  99         {
 100         CONF_MODULE *pmod;
 101         char *name;
 102         char *value;
 103         unsigned long flags;
 104         void *usr_data;
 105         };
 106 
 107 static STACK_OF(CONF_MODULE) *supported_modules = NULL;
 108 static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
 109 
 110 static void module_free(CONF_MODULE *md);
 111 static void module_finish(CONF_IMODULE *imod);
 112 static int module_run(const CONF *cnf, char *name, char *value,
 113                                           unsigned long flags);
 114 static CONF_MODULE *module_add(DSO *dso, const char *name,
 115                         conf_init_func *ifunc, conf_finish_func *ffunc);
 116 static CONF_MODULE *module_find(char *name);
 117 static int module_init(CONF_MODULE *pmod, char *name, char *value,
 118                                            const CONF *cnf);
 119 static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
 120                                                                         unsigned long flags);
 121 
 122 /* Main function: load modules from a CONF structure */
 123 
 124 int CONF_modules_load(const CONF *cnf, const char *appname,
 125                       unsigned long flags)
 126         {
 127         STACK_OF(CONF_VALUE) *values;
 128         CONF_VALUE *vl;
 129         char *vsection = NULL;
 130 
 131         int ret, i;
 132 
 133         if (!cnf)
 134                 return 1;
 135 
 136         if (appname)
 137                 vsection = NCONF_get_string(cnf, NULL, appname);
 138 
 139         if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION)))
 140                 vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
 141 
 142         if (!vsection)
 143                 {
 144                 ERR_clear_error();
 145                 return 1;
 146                 }
 147 
 148         values = NCONF_get_section(cnf, vsection);
 149 
 150         if (!values)
 151                 return 0;
 152 
 153         for (i = 0; i < sk_CONF_VALUE_num(values); i++)
 154                 {
 155                 vl = sk_CONF_VALUE_value(values, i);
 156                 ret = module_run(cnf, vl->name, vl->value, flags);
 157                 if (ret <= 0)
 158                         if(!(flags & CONF_MFLAGS_IGNORE_ERRORS))
 159                                 return ret;
 160                 }
 161 
 162         return 1;
 163 
 164         }
 165 
 166 int CONF_modules_load_file(const char *filename, const char *appname,
 167                            unsigned long flags)
 168         {
 169         char *file = NULL;
 170         CONF *conf = NULL;
 171         int ret = 0;
 172         conf = NCONF_new(NULL);
 173         if (!conf)
 174                 goto err;
 175 
 176         if (filename == NULL)
 177                 {
 178                 file = CONF_get1_default_config_file();
 179                 if (!file)
 180                         goto err;
 181                 }
 182         else
 183                 file = (char *)filename;
 184 
 185         if (NCONF_load(conf, file, NULL) <= 0)
 186                 {
 187                 if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
 188                   (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE))
 189                         {
 190                         ERR_clear_error();
 191                         ret = 1;
 192                         }
 193                 goto err;
 194                 }
 195 
 196         ret = CONF_modules_load(conf, appname, flags);
 197 
 198         err:
 199         if (filename == NULL)
 200                 OPENSSL_free(file);
 201         NCONF_free(conf);
 202 
 203         return ret;
 204         }
 205 
 206 static int module_run(const CONF *cnf, char *name, char *value,
 207                       unsigned long flags)
 208         {
 209         CONF_MODULE *md;
 210         int ret;
 211 
 212         md = module_find(name);
 213 
 214         /* Module not found: try to load DSO */
 215         if (!md && !(flags & CONF_MFLAGS_NO_DSO))
 216                 md = module_load_dso(cnf, name, value, flags);
 217 
 218         if (!md)
 219                 {
 220                 if (!(flags & CONF_MFLAGS_SILENT))
 221                         {
 222                         CONFerr(CONF_F_MODULE_RUN, CONF_R_UNKNOWN_MODULE_NAME);
 223                         ERR_add_error_data(2, "module=", name);
 224                         }
 225                 return -1;
 226                 }
 227 
 228         ret = module_init(md, name, value, cnf);
 229 
 230         if (ret <= 0)
 231                 {
 232                 if (!(flags & CONF_MFLAGS_SILENT))
 233                         {
 234                         char rcode[DECIMAL_SIZE(ret)+1];
 235                         CONFerr(CONF_F_MODULE_RUN, CONF_R_MODULE_INITIALIZATION_ERROR);
 236                         BIO_snprintf(rcode, sizeof rcode, "%-8d", ret);
 237                         ERR_add_error_data(6, "module=", name, ", value=", value, ", retcode=", rcode);
 238                         }
 239                 }
 240 
 241         return ret;
 242         }
 243 
 244 /* Load a module from a DSO */
 245 static CONF_MODULE *module_load_dso(const CONF *cnf, char *name, char *value,
 246                                     unsigned long flags)
 247         {
 248         DSO *dso = NULL;
 249         conf_init_func *ifunc;
 250         conf_finish_func *ffunc;
 251         char *path = NULL;
 252         int errcode = 0;
 253         CONF_MODULE *md;
 254         /* Look for alternative path in module section */
 255         path = NCONF_get_string(cnf, value, "path");
 256         if (!path)
 257                 {
 258                 ERR_clear_error();
 259                 path = name;
 260                 }
 261         dso = DSO_load(NULL, path, NULL, 0);
 262         if (!dso)
 263                 {
 264                 errcode = CONF_R_ERROR_LOADING_DSO;
 265                 goto err;
 266                 }
 267         ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name);
 268         if (!ifunc)
 269                 {
 270                 errcode = CONF_R_MISSING_INIT_FUNCTION;
 271                 goto err;
 272                 }
 273         ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name);
 274         /* All OK, add module */
 275         md = module_add(dso, name, ifunc, ffunc);
 276 
 277         if (!md)
 278                 goto err;
 279 
 280         return md;
 281 
 282         err:
 283         if (dso)
 284                 DSO_free(dso);
 285         CONFerr(CONF_F_MODULE_LOAD_DSO, errcode);
 286         ERR_add_error_data(4, "module=", name, ", path=", path);
 287         return NULL;
 288         }
 289 
 290 /* add module to list */
 291 static CONF_MODULE *module_add(DSO *dso, const char *name,
 292                                conf_init_func *ifunc, conf_finish_func *ffunc)
 293         {
 294         CONF_MODULE *tmod = NULL;
 295         if (supported_modules == NULL)
 296                 supported_modules = sk_CONF_MODULE_new_null();
 297         if (supported_modules == NULL)
 298                 return NULL;
 299         tmod = OPENSSL_malloc(sizeof(CONF_MODULE));
 300         if (tmod == NULL)
 301                 return NULL;
 302 
 303         tmod->dso = dso;
 304         tmod->name = BUF_strdup(name);
 305         tmod->init = ifunc;
 306         tmod->finish = ffunc;
 307         tmod->links = 0;
 308 
 309         if (!sk_CONF_MODULE_push(supported_modules, tmod))
 310                 {
 311                 OPENSSL_free(tmod);
 312                 return NULL;
 313                 }
 314 
 315         return tmod;
 316         }
 317 
 318 /* Find a module from the list. We allow module names of the
 319  * form modname.XXXX to just search for modname to allow the
 320  * same module to be initialized more than once.
 321  */
 322 
 323 static CONF_MODULE *module_find(char *name)
 324         {
 325         CONF_MODULE *tmod;
 326         int i, nchar;
 327         char *p;
 328         p = strrchr(name, '.');
 329 
 330         if (p)
 331                 nchar = p - name;
 332         else
 333                 nchar = strlen(name);
 334 
 335         for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++)
 336                 {
 337                 tmod = sk_CONF_MODULE_value(supported_modules, i);
 338                 if (!strncmp(tmod->name, name, nchar))
 339                         return tmod;
 340                 }
 341 
 342         return NULL;
 343 
 344         }
 345 
 346 /* initialize a module */
 347 static int module_init(CONF_MODULE *pmod, char *name, char *value,
 348                        const CONF *cnf)
 349         {
 350         int ret = 1;
 351         int init_called = 0;
 352         CONF_IMODULE *imod = NULL;
 353 
 354         /* Otherwise add initialized module to list */
 355         imod = OPENSSL_malloc(sizeof(CONF_IMODULE));
 356         if (!imod)
 357                 goto err;
 358 
 359         imod->pmod = pmod;
 360         imod->name = BUF_strdup(name);
 361         imod->value = BUF_strdup(value);
 362         imod->usr_data = NULL;
 363 
 364         if (!imod->name || !imod->value)
 365                 goto memerr;
 366 
 367         /* Try to initialize module */
 368         if(pmod->init)
 369                 {
 370                 ret = pmod->init(imod, cnf);
 371                 init_called = 1;
 372                 /* Error occurred, exit */
 373                 if (ret <= 0)
 374                         goto err;
 375                 }
 376 
 377         if (initialized_modules == NULL)
 378                 {
 379                 initialized_modules = sk_CONF_IMODULE_new_null();
 380                 if (!initialized_modules)
 381                         {
 382                         CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
 383                         goto err;
 384                         }
 385                 }
 386 
 387         if (!sk_CONF_IMODULE_push(initialized_modules, imod))
 388                 {
 389                 CONFerr(CONF_F_MODULE_INIT, ERR_R_MALLOC_FAILURE);
 390                 goto err;
 391                 }
 392 
 393         pmod->links++;
 394 
 395         return ret;
 396 
 397         err:
 398 
 399         /* We've started the module so we'd better finish it */
 400         if (pmod->finish && init_called)
 401                 pmod->finish(imod);
 402 
 403         memerr:
 404         if (imod)
 405                 {
 406                 if (imod->name)
 407                         OPENSSL_free(imod->name);
 408                 if (imod->value)
 409                         OPENSSL_free(imod->value);
 410                 OPENSSL_free(imod);
 411                 }
 412 
 413         return -1;
 414 
 415         }
 416 
 417 /* Unload any dynamic modules that have a link count of zero:
 418  * i.e. have no active initialized modules. If 'all' is set
 419  * then all modules are unloaded including static ones.
 420  */
 421 
 422 void CONF_modules_unload(int all)
 423         {
 424         int i;
 425         CONF_MODULE *md;
 426         CONF_modules_finish();
 427         /* unload modules in reverse order */
 428         for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--)
 429                 {
 430                 md = sk_CONF_MODULE_value(supported_modules, i);
 431                 /* If static or in use and 'all' not set ignore it */
 432                 if (((md->links > 0) || !md->dso) && !all)
 433                         continue;
 434                 /* Since we're working in reverse this is OK */
 435                 (void)sk_CONF_MODULE_delete(supported_modules, i);
 436                 module_free(md);
 437                 }
 438         if (sk_CONF_MODULE_num(supported_modules) == 0)
 439                 {
 440                 sk_CONF_MODULE_free(supported_modules);
 441                 supported_modules = NULL;
 442                 }
 443         }
 444 
 445 /* unload a single module */
 446 static void module_free(CONF_MODULE *md)
 447         {
 448         if (md->dso)
 449                 DSO_free(md->dso);
 450         OPENSSL_free(md->name);
 451         OPENSSL_free(md);
 452         }
 453 
 454 /* finish and free up all modules instances */
 455 
 456 void CONF_modules_finish(void)
 457         {
 458         CONF_IMODULE *imod;
 459         while (sk_CONF_IMODULE_num(initialized_modules) > 0)
 460                 {
 461                 imod = sk_CONF_IMODULE_pop(initialized_modules);
 462                 module_finish(imod);
 463                 }
 464         sk_CONF_IMODULE_free(initialized_modules);
 465         initialized_modules = NULL;
 466         }
 467 
 468 /* finish a module instance */
 469 
 470 static void module_finish(CONF_IMODULE *imod)
 471         {
 472         if (imod->pmod->finish)
 473                 imod->pmod->finish(imod);
 474         imod->pmod->links--;
 475         OPENSSL_free(imod->name);
 476         OPENSSL_free(imod->value);
 477         OPENSSL_free(imod);
 478         }
 479 
 480 /* Add a static module to OpenSSL */
 481 
 482 int CONF_module_add(const char *name, conf_init_func *ifunc,
 483                     conf_finish_func *ffunc)
 484         {
 485         if (module_add(NULL, name, ifunc, ffunc))
 486                 return 1;
 487         else
 488                 return 0;
 489         }
 490 
 491 void CONF_modules_free(void)
 492         {
 493         CONF_modules_finish();
 494         CONF_modules_unload(1);
 495         }
 496 
 497 /* Utility functions */
 498 
 499 const char *CONF_imodule_get_name(const CONF_IMODULE *md)
 500         {
 501         return md->name;
 502         }
 503 
 504 const char *CONF_imodule_get_value(const CONF_IMODULE *md)
 505         {
 506         return md->value;
 507         }
 508 
 509 void *CONF_imodule_get_usr_data(const CONF_IMODULE *md)
 510         {
 511         return md->usr_data;
 512         }
 513 
 514 void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
 515         {
 516         md->usr_data = usr_data;
 517         }
 518 
 519 CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md)
 520         {
 521         return md->pmod;
 522         }
 523 
 524 unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md)
 525         {
 526         return md->flags;
 527         }
 528 
 529 void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags)
 530         {
 531         md->flags = flags;
 532         }
 533 
 534 void *CONF_module_get_usr_data(CONF_MODULE *pmod)
 535         {
 536         return pmod->usr_data;
 537         }
 538 
 539 void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
 540         {
 541         pmod->usr_data = usr_data;
 542         }
 543 
 544 /* Return default config file name */
 545 
 546 char *CONF_get1_default_config_file(void)
 547         {
 548         char *file;
 549         int len;
 550 
 551         file = getenv("OPENSSL_CONF");
 552         if (file)
 553                 return BUF_strdup(file);
 554 
 555         len = strlen(X509_get_default_cert_area());
 556 #ifndef OPENSSL_SYS_VMS
 557         len++;
 558 #endif
 559         len += strlen(OPENSSL_CONF);
 560 
 561         file = OPENSSL_malloc(len + 1);
 562 
 563         if (!file)
 564                 return NULL;
 565         BUF_strlcpy(file,X509_get_default_cert_area(),len + 1);
 566 #ifndef OPENSSL_SYS_VMS
 567         BUF_strlcat(file,"/",len + 1);
 568 #endif
 569         BUF_strlcat(file,OPENSSL_CONF,len + 1);
 570 
 571         return file;
 572         }
 573 
 574 /* This function takes a list separated by 'sep' and calls the
 575  * callback function giving the start and length of each member
 576  * optionally stripping leading and trailing whitespace. This can
 577  * be used to parse comma separated lists for example.
 578  */
 579 
 580 int CONF_parse_list(const char *list_, int sep, int nospc,
 581         int (*list_cb)(const char *elem, int len, void *usr), void *arg)
 582         {
 583         int ret;
 584         const char *lstart, *tmpend, *p;
 585 
 586         if(list_ == NULL)
 587                 {
 588                 CONFerr(CONF_F_CONF_PARSE_LIST, CONF_R_LIST_CANNOT_BE_NULL);
 589                 return 0;
 590                 }
 591 
 592         lstart = list_;
 593         for(;;)
 594                 {
 595                 if (nospc)
 596                         {
 597                         while(*lstart && isspace((unsigned char)*lstart))
 598                                 lstart++;
 599                         }
 600                 p = strchr(lstart, sep);
 601                 if (p == lstart || !*lstart)
 602                         ret = list_cb(NULL, 0, arg);
 603                 else
 604                         {
 605                         if (p)
 606                                 tmpend = p - 1;
 607                         else
 608                                 tmpend = lstart + strlen(lstart) - 1;
 609                         if (nospc)
 610                                 {
 611                                 while(isspace((unsigned char)*tmpend))
 612                                         tmpend--;
 613                                 }
 614                         ret = list_cb(lstart, tmpend - lstart + 1, arg);
 615                         }
 616                 if (ret <= 0)
 617                         return ret;
 618                 if (p == NULL)
 619                         return 1;
 620                 lstart = p + 1;
 621                 }
 622         }