Home | History | Annotate | Line # | Download | only in apps
      1 /*
      2  * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <internal/cryptlib.h>
     11 #include <stdio.h>
     12 #include <string.h>
     13 #include <stdlib.h>
     14 #include <openssl/bio.h>
     15 #include <openssl/crypto.h>
     16 #include <openssl/lhash.h>
     17 #include <openssl/conf.h>
     18 #include <openssl/x509.h>
     19 #include <openssl/pem.h>
     20 #include <openssl/ssl.h>
     21 #ifndef OPENSSL_NO_ENGINE
     22 # include <openssl/engine.h>
     23 #endif
     24 #include <openssl/err.h>
     25 /* Needed to get the other O_xxx flags. */
     26 #ifdef OPENSSL_SYS_VMS
     27 # include <unixio.h>
     28 #endif
     29 #include "apps.h"
     30 #define INCLUDE_FUNCTION_TABLE
     31 #include "progs.h"
     32 
     33 /* Structure to hold the number of columns to be displayed and the
     34  * field width used to display them.
     35  */
     36 typedef struct {
     37     int columns;
     38     int width;
     39 } DISPLAY_COLUMNS;
     40 
     41 /* Special sentinel to exit the program. */
     42 #define EXIT_THE_PROGRAM (-1)
     43 
     44 /*
     45  * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
     46  * the base prototypes (we cast each variable inside the function to the
     47  * required type of "FUNCTION*"). This removes the necessity for
     48  * macro-generated wrapper functions.
     49  */
     50 static LHASH_OF(FUNCTION) *prog_init(void);
     51 static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
     52 static void list_pkey(void);
     53 static void list_pkey_meth(void);
     54 static void list_type(FUNC_TYPE ft, int one);
     55 static void list_disabled(void);
     56 char *default_config_file = NULL;
     57 
     58 BIO *bio_in = NULL;
     59 BIO *bio_out = NULL;
     60 BIO *bio_err = NULL;
     61 
     62 static void calculate_columns(DISPLAY_COLUMNS *dc)
     63 {
     64     FUNCTION *f;
     65     int len, maxlen = 0;
     66 
     67     for (f = functions; f->name != NULL; ++f)
     68         if (f->type == FT_general || f->type == FT_md || f->type == FT_cipher)
     69             if ((len = strlen(f->name)) > maxlen)
     70                 maxlen = len;
     71 
     72     dc->width = maxlen + 2;
     73     dc->columns = (80 - 1) / dc->width;
     74 }
     75 
     76 static int apps_startup(void)
     77 {
     78 #ifdef SIGPIPE
     79     signal(SIGPIPE, SIG_IGN);
     80 #endif
     81 
     82     /* Set non-default library initialisation settings */
     83     if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN
     84                           | OPENSSL_INIT_LOAD_CONFIG, NULL))
     85         return 0;
     86 
     87     setup_ui_method();
     88 
     89     return 1;
     90 }
     91 
     92 static void apps_shutdown(void)
     93 {
     94     destroy_ui_method();
     95     destroy_prefix_method();
     96 }
     97 
     98 static char *make_config_name(void)
     99 {
    100     const char *t;
    101     size_t len;
    102     char *p;
    103 
    104     if ((t = getenv("OPENSSL_CONF")) != NULL)
    105         return OPENSSL_strdup(t);
    106 
    107     t = X509_get_default_cert_area();
    108     len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1;
    109     p = app_malloc(len, "config filename buffer");
    110     strcpy(p, t);
    111 #ifndef OPENSSL_SYS_VMS
    112     strcat(p, "/");
    113 #endif
    114     strcat(p, OPENSSL_CONF);
    115 
    116     return p;
    117 }
    118 
    119 int main(int argc, char *argv[])
    120 {
    121     FUNCTION f, *fp;
    122     LHASH_OF(FUNCTION) *prog = NULL;
    123     char *p, *pname;
    124     char buf[1024];
    125     const char *prompt;
    126     ARGS arg;
    127     int first, n, i, ret = 0;
    128 
    129     arg.argv = NULL;
    130     arg.size = 0;
    131 
    132     /* Set up some of the environment. */
    133     default_config_file = make_config_name();
    134     bio_in = dup_bio_in(FORMAT_TEXT);
    135     bio_out = dup_bio_out(FORMAT_TEXT);
    136     bio_err = dup_bio_err(FORMAT_TEXT);
    137 
    138 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
    139     argv = copy_argv(&argc, argv);
    140 #elif defined(_WIN32)
    141     /*
    142      * Replace argv[] with UTF-8 encoded strings.
    143      */
    144     win32_utf8argv(&argc, &argv);
    145 #endif
    146 
    147     p = getenv("OPENSSL_DEBUG_MEMORY");
    148     if (p != NULL && strcmp(p, "on") == 0)
    149         CRYPTO_set_mem_debug(1);
    150     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
    151 
    152     if (getenv("OPENSSL_FIPS")) {
    153         BIO_printf(bio_err, "FIPS mode not supported.\n");
    154         return 1;
    155     }
    156 
    157     if (!apps_startup()) {
    158         BIO_printf(bio_err,
    159                    "FATAL: Startup failure (dev note: apps_startup() failed)\n");
    160         ERR_print_errors(bio_err);
    161         ret = 1;
    162         goto end;
    163     }
    164 
    165     prog = prog_init();
    166     if (prog == NULL) {
    167         BIO_printf(bio_err,
    168                    "FATAL: Startup failure (dev note: prog_init() failed)\n");
    169         ERR_print_errors(bio_err);
    170         ret = 1;
    171         goto end;
    172     }
    173     pname = opt_progname(argv[0]);
    174 
    175     /* first check the program name */
    176     f.name = pname;
    177     fp = lh_FUNCTION_retrieve(prog, &f);
    178     if (fp != NULL) {
    179         argv[0] = pname;
    180         ret = fp->func(argc, argv);
    181         goto end;
    182     }
    183 
    184     /* If there is stuff on the command line, run with that. */
    185     if (argc != 1) {
    186         argc--;
    187         argv++;
    188         ret = do_cmd(prog, argc, argv);
    189         if (ret < 0)
    190             ret = 0;
    191         goto end;
    192     }
    193 
    194     /* ok, lets enter interactive mode */
    195     for (;;) {
    196         ret = 0;
    197         /* Read a line, continue reading if line ends with \ */
    198         for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) {
    199             prompt = first ? "OpenSSL> " : "> ";
    200             p[0] = '\0';
    201 #ifndef READLINE
    202             fputs(prompt, stdout);
    203             fflush(stdout);
    204             if (!fgets(p, n, stdin))
    205                 goto end;
    206             if (p[0] == '\0')
    207                 goto end;
    208             i = strlen(p);
    209             if (i <= 1)
    210                 break;
    211             if (p[i - 2] != '\\')
    212                 break;
    213             i -= 2;
    214             p += i;
    215             n -= i;
    216 #else
    217             {
    218                 extern char *readline(const char *);
    219                 extern void add_history(const char *cp);
    220                 char *text;
    221 
    222                 text = readline(prompt);
    223                 if (text == NULL)
    224                     goto end;
    225                 i = strlen(text);
    226                 if (i == 0 || i > n)
    227                     break;
    228                 if (text[i - 1] != '\\') {
    229                     p += strlen(strcpy(p, text));
    230                     free(text);
    231                     add_history(buf);
    232                     break;
    233                 }
    234 
    235                 text[i - 1] = '\0';
    236                 p += strlen(strcpy(p, text));
    237                 free(text);
    238                 n -= i;
    239             }
    240 #endif
    241         }
    242 
    243         if (!chopup_args(&arg, buf)) {
    244             BIO_printf(bio_err, "Can't parse (no memory?)\n");
    245             break;
    246         }
    247 
    248         ret = do_cmd(prog, arg.argc, arg.argv);
    249         if (ret == EXIT_THE_PROGRAM) {
    250             ret = 0;
    251             goto end;
    252         }
    253         if (ret != 0)
    254             BIO_printf(bio_err, "error in %s\n", arg.argv[0]);
    255         (void)BIO_flush(bio_out);
    256         (void)BIO_flush(bio_err);
    257     }
    258     ret = 1;
    259  end:
    260     OPENSSL_free(default_config_file);
    261     lh_FUNCTION_free(prog);
    262     OPENSSL_free(arg.argv);
    263     app_RAND_write();
    264 
    265     BIO_free(bio_in);
    266     BIO_free_all(bio_out);
    267     apps_shutdown();
    268 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
    269     if (CRYPTO_mem_leaks(bio_err) <= 0)
    270         ret = 1;
    271 #endif
    272     BIO_free(bio_err);
    273     EXIT(ret);
    274 }
    275 
    276 static void list_cipher_fn(const EVP_CIPHER *c,
    277                            const char *from, const char *to, void *arg)
    278 {
    279     if (c != NULL) {
    280         BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
    281     } else {
    282         if (from == NULL)
    283             from = "<undefined>";
    284         if (to == NULL)
    285             to = "<undefined>";
    286         BIO_printf(arg, "%s => %s\n", from, to);
    287     }
    288 }
    289 
    290 static void list_md_fn(const EVP_MD *m,
    291                        const char *from, const char *to, void *arg)
    292 {
    293     if (m != NULL) {
    294         BIO_printf(arg, "%s\n", EVP_MD_name(m));
    295     } else {
    296         if (from == NULL)
    297             from = "<undefined>";
    298         if (to == NULL)
    299             to = "<undefined>";
    300         BIO_printf((BIO *)arg, "%s => %s\n", from, to);
    301     }
    302 }
    303 
    304 static void list_missing_help(void)
    305 {
    306     const FUNCTION *fp;
    307     const OPTIONS *o;
    308 
    309     for (fp = functions; fp->name != NULL; fp++) {
    310         if ((o = fp->help) != NULL) {
    311             /* If there is help, list what flags are not documented. */
    312             for ( ; o->name != NULL; o++) {
    313                 if (o->helpstr == NULL)
    314                     BIO_printf(bio_out, "%s %s\n", fp->name, o->name);
    315             }
    316         } else if (fp->func != dgst_main) {
    317             /* If not aliased to the dgst command, */
    318             BIO_printf(bio_out, "%s *\n", fp->name);
    319         }
    320     }
    321 }
    322 
    323 static void list_options_for_command(const char *command)
    324 {
    325     const FUNCTION *fp;
    326     const OPTIONS *o;
    327 
    328     for (fp = functions; fp->name != NULL; fp++)
    329         if (strcmp(fp->name, command) == 0)
    330             break;
    331     if (fp->name == NULL) {
    332         BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
    333                 command);
    334         return;
    335     }
    336 
    337     if ((o = fp->help) == NULL)
    338         return;
    339 
    340     for ( ; o->name != NULL; o++) {
    341         if (o->name == OPT_HELP_STR
    342                 || o->name == OPT_MORE_STR
    343                 || o->name[0] == '\0')
    344             continue;
    345         BIO_printf(bio_out, "%s %c\n", o->name, o->valtype);
    346     }
    347 }
    348 
    349 
    350 /* Unified enum for help and list commands. */
    351 typedef enum HELPLIST_CHOICE {
    352     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE,
    353     OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_OPTIONS,
    354     OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
    355     OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_MISSING_HELP
    356 } HELPLIST_CHOICE;
    357 
    358 const OPTIONS list_options[] = {
    359     {"help", OPT_HELP, '-', "Display this summary"},
    360     {"1", OPT_ONE, '-', "List in one column"},
    361     {"commands", OPT_COMMANDS, '-', "List of standard commands"},
    362     {"digest-commands", OPT_DIGEST_COMMANDS, '-',
    363      "List of message digest commands"},
    364     {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
    365      "List of message digest algorithms"},
    366     {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"},
    367     {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
    368      "List of cipher algorithms"},
    369     {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
    370      "List of public key algorithms"},
    371     {"public-key-methods", OPT_PK_METHOD, '-',
    372      "List of public key methods"},
    373     {"disabled", OPT_DISABLED, '-',
    374      "List of disabled features"},
    375     {"missing-help", OPT_MISSING_HELP, '-',
    376      "List missing detailed help strings"},
    377     {"options", OPT_OPTIONS, 's',
    378      "List options for specified command"},
    379     {NULL}
    380 };
    381 
    382 int list_main(int argc, char **argv)
    383 {
    384     char *prog;
    385     HELPLIST_CHOICE o;
    386     int one = 0, done = 0;
    387 
    388     prog = opt_init(argc, argv, list_options);
    389     while ((o = opt_next()) != OPT_EOF) {
    390         switch (o) {
    391         case OPT_EOF:  /* Never hit, but suppresses warning */
    392         case OPT_ERR:
    393 opthelp:
    394             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
    395             return 1;
    396         case OPT_HELP:
    397             opt_help(list_options);
    398             break;
    399         case OPT_ONE:
    400             one = 1;
    401             break;
    402         case OPT_COMMANDS:
    403             list_type(FT_general, one);
    404             break;
    405         case OPT_DIGEST_COMMANDS:
    406             list_type(FT_md, one);
    407             break;
    408         case OPT_DIGEST_ALGORITHMS:
    409             EVP_MD_do_all_sorted(list_md_fn, bio_out);
    410             break;
    411         case OPT_CIPHER_COMMANDS:
    412             list_type(FT_cipher, one);
    413             break;
    414         case OPT_CIPHER_ALGORITHMS:
    415             EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
    416             break;
    417         case OPT_PK_ALGORITHMS:
    418             list_pkey();
    419             break;
    420         case OPT_PK_METHOD:
    421             list_pkey_meth();
    422             break;
    423         case OPT_DISABLED:
    424             list_disabled();
    425             break;
    426         case OPT_MISSING_HELP:
    427             list_missing_help();
    428             break;
    429         case OPT_OPTIONS:
    430             list_options_for_command(opt_arg());
    431             break;
    432         }
    433         done = 1;
    434     }
    435     if (opt_num_rest() != 0) {
    436         BIO_printf(bio_err, "Extra arguments given.\n");
    437         goto opthelp;
    438     }
    439 
    440     if (!done)
    441         goto opthelp;
    442 
    443     return 0;
    444 }
    445 
    446 typedef enum HELP_CHOICE {
    447     OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP
    448 } HELP_CHOICE;
    449 
    450 const OPTIONS help_options[] = {
    451     {OPT_HELP_STR, 1, '-', "Usage: help [options]\n"},
    452     {OPT_HELP_STR, 1, '-', "       help [command]\n"},
    453     {"help", OPT_hHELP, '-', "Display this summary"},
    454     {NULL}
    455 };
    456 
    457 
    458 int help_main(int argc, char **argv)
    459 {
    460     FUNCTION *fp;
    461     int i, nl;
    462     FUNC_TYPE tp;
    463     char *prog;
    464     HELP_CHOICE o;
    465     DISPLAY_COLUMNS dc;
    466 
    467     prog = opt_init(argc, argv, help_options);
    468     while ((o = opt_next()) != OPT_hEOF) {
    469         switch (o) {
    470         case OPT_hERR:
    471         case OPT_hEOF:
    472             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
    473             return 1;
    474         case OPT_hHELP:
    475             opt_help(help_options);
    476             return 0;
    477         }
    478     }
    479 
    480     if (opt_num_rest() == 1) {
    481         char *new_argv[3];
    482 
    483         new_argv[0] = opt_rest()[0];
    484         new_argv[1] = "--help";
    485         new_argv[2] = NULL;
    486         return do_cmd(prog_init(), 2, new_argv);
    487     }
    488     if (opt_num_rest() != 0) {
    489         BIO_printf(bio_err, "Usage: %s\n", prog);
    490         return 1;
    491     }
    492 
    493     calculate_columns(&dc);
    494     BIO_printf(bio_err, "Standard commands");
    495     i = 0;
    496     tp = FT_none;
    497     for (fp = functions; fp->name != NULL; fp++) {
    498         nl = 0;
    499         if (i++ % dc.columns == 0) {
    500             BIO_printf(bio_err, "\n");
    501             nl = 1;
    502         }
    503         if (fp->type != tp) {
    504             tp = fp->type;
    505             if (!nl)
    506                 BIO_printf(bio_err, "\n");
    507             if (tp == FT_md) {
    508                 i = 1;
    509                 BIO_printf(bio_err,
    510                            "\nMessage Digest commands (see the `dgst' command for more details)\n");
    511             } else if (tp == FT_cipher) {
    512                 i = 1;
    513                 BIO_printf(bio_err,
    514                            "\nCipher commands (see the `enc' command for more details)\n");
    515             }
    516         }
    517         BIO_printf(bio_err, "%-*s", dc.width, fp->name);
    518     }
    519     BIO_printf(bio_err, "\n\n");
    520     return 0;
    521 }
    522 
    523 static void list_type(FUNC_TYPE ft, int one)
    524 {
    525     FUNCTION *fp;
    526     int i = 0;
    527     DISPLAY_COLUMNS dc = {0};
    528 
    529     if (!one)
    530         calculate_columns(&dc);
    531 
    532     for (fp = functions; fp->name != NULL; fp++) {
    533         if (fp->type != ft)
    534             continue;
    535         if (one) {
    536             BIO_printf(bio_out, "%s\n", fp->name);
    537         } else {
    538             if (i % dc.columns == 0 && i > 0)
    539                 BIO_printf(bio_out, "\n");
    540             BIO_printf(bio_out, "%-*s", dc.width, fp->name);
    541             i++;
    542         }
    543     }
    544     if (!one)
    545         BIO_printf(bio_out, "\n\n");
    546 }
    547 
    548 static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
    549 {
    550     FUNCTION f, *fp;
    551 
    552     if (argc <= 0 || argv[0] == NULL)
    553         return 0;
    554     f.name = argv[0];
    555     fp = lh_FUNCTION_retrieve(prog, &f);
    556     if (fp == NULL) {
    557         if (EVP_get_digestbyname(argv[0])) {
    558             f.type = FT_md;
    559             f.func = dgst_main;
    560             fp = &f;
    561         } else if (EVP_get_cipherbyname(argv[0])) {
    562             f.type = FT_cipher;
    563             f.func = enc_main;
    564             fp = &f;
    565         }
    566     }
    567     if (fp != NULL) {
    568         return fp->func(argc, argv);
    569     }
    570     if ((strncmp(argv[0], "no-", 3)) == 0) {
    571         /*
    572          * User is asking if foo is unsupported, by trying to "run" the
    573          * no-foo command.  Strange.
    574          */
    575         f.name = argv[0] + 3;
    576         if (lh_FUNCTION_retrieve(prog, &f) == NULL) {
    577             BIO_printf(bio_out, "%s\n", argv[0]);
    578             return 0;
    579         }
    580         BIO_printf(bio_out, "%s\n", argv[0] + 3);
    581         return 1;
    582     }
    583     if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 ||
    584         strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0)
    585         /* Special value to mean "exit the program. */
    586         return EXIT_THE_PROGRAM;
    587 
    588     BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
    589                argv[0]);
    590     return 1;
    591 }
    592 
    593 static void list_pkey(void)
    594 {
    595     int i;
    596 
    597     for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
    598         const EVP_PKEY_ASN1_METHOD *ameth;
    599         int pkey_id, pkey_base_id, pkey_flags;
    600         const char *pinfo, *pem_str;
    601         ameth = EVP_PKEY_asn1_get0(i);
    602         EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
    603                                 &pinfo, &pem_str, ameth);
    604         if (pkey_flags & ASN1_PKEY_ALIAS) {
    605             BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id));
    606             BIO_printf(bio_out, "\tAlias for: %s\n",
    607                        OBJ_nid2ln(pkey_base_id));
    608         } else {
    609             BIO_printf(bio_out, "Name: %s\n", pinfo);
    610             BIO_printf(bio_out, "\tType: %s Algorithm\n",
    611                        pkey_flags & ASN1_PKEY_DYNAMIC ?
    612                        "External" : "Builtin");
    613             BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
    614             if (pem_str == NULL)
    615                 pem_str = "(none)";
    616             BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
    617         }
    618 
    619     }
    620 }
    621 
    622 static void list_pkey_meth(void)
    623 {
    624     size_t i;
    625     size_t meth_count = EVP_PKEY_meth_get_count();
    626 
    627     for (i = 0; i < meth_count; i++) {
    628         const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i);
    629         int pkey_id, pkey_flags;
    630 
    631         EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth);
    632         BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id));
    633         BIO_printf(bio_out, "\tType: %s Algorithm\n",
    634                    pkey_flags & ASN1_PKEY_DYNAMIC ?  "External" : "Builtin");
    635     }
    636 }
    637 
    638 static int function_cmp(const FUNCTION * a, const FUNCTION * b)
    639 {
    640     return strncmp(a->name, b->name, 8);
    641 }
    642 
    643 static unsigned long function_hash(const FUNCTION * a)
    644 {
    645     return OPENSSL_LH_strhash(a->name);
    646 }
    647 
    648 static int SortFnByName(const void *_f1, const void *_f2)
    649 {
    650     const FUNCTION *f1 = _f1;
    651     const FUNCTION *f2 = _f2;
    652 
    653     if (f1->type != f2->type)
    654         return f1->type - f2->type;
    655     return strcmp(f1->name, f2->name);
    656 }
    657 
    658 static void list_disabled(void)
    659 {
    660     BIO_puts(bio_out, "Disabled algorithms:\n");
    661 #ifdef OPENSSL_NO_ARIA
    662     BIO_puts(bio_out, "ARIA\n");
    663 #endif
    664 #ifdef OPENSSL_NO_BF
    665     BIO_puts(bio_out, "BF\n");
    666 #endif
    667 #ifdef OPENSSL_NO_BLAKE2
    668     BIO_puts(bio_out, "BLAKE2\n");
    669 #endif
    670 #ifdef OPENSSL_NO_CAMELLIA
    671     BIO_puts(bio_out, "CAMELLIA\n");
    672 #endif
    673 #ifdef OPENSSL_NO_CAST
    674     BIO_puts(bio_out, "CAST\n");
    675 #endif
    676 #ifdef OPENSSL_NO_CMAC
    677     BIO_puts(bio_out, "CMAC\n");
    678 #endif
    679 #ifdef OPENSSL_NO_CMS
    680     BIO_puts(bio_out, "CMS\n");
    681 #endif
    682 #ifdef OPENSSL_NO_COMP
    683     BIO_puts(bio_out, "COMP\n");
    684 #endif
    685 #ifdef OPENSSL_NO_DES
    686     BIO_puts(bio_out, "DES\n");
    687 #endif
    688 #ifdef OPENSSL_NO_DGRAM
    689     BIO_puts(bio_out, "DGRAM\n");
    690 #endif
    691 #ifdef OPENSSL_NO_DH
    692     BIO_puts(bio_out, "DH\n");
    693 #endif
    694 #ifdef OPENSSL_NO_DSA
    695     BIO_puts(bio_out, "DSA\n");
    696 #endif
    697 #if defined(OPENSSL_NO_DTLS)
    698     BIO_puts(bio_out, "DTLS\n");
    699 #endif
    700 #if defined(OPENSSL_NO_DTLS1)
    701     BIO_puts(bio_out, "DTLS1\n");
    702 #endif
    703 #if defined(OPENSSL_NO_DTLS1_2)
    704     BIO_puts(bio_out, "DTLS1_2\n");
    705 #endif
    706 #ifdef OPENSSL_NO_EC
    707     BIO_puts(bio_out, "EC\n");
    708 #endif
    709 #ifdef OPENSSL_NO_EC2M
    710     BIO_puts(bio_out, "EC2M\n");
    711 #endif
    712 #ifdef OPENSSL_NO_ENGINE
    713     BIO_puts(bio_out, "ENGINE\n");
    714 #endif
    715 #ifdef OPENSSL_NO_GOST
    716     BIO_puts(bio_out, "GOST\n");
    717 #endif
    718 #ifdef OPENSSL_NO_HEARTBEATS
    719     BIO_puts(bio_out, "HEARTBEATS\n");
    720 #endif
    721 #ifdef OPENSSL_NO_IDEA
    722     BIO_puts(bio_out, "IDEA\n");
    723 #endif
    724 #ifdef OPENSSL_NO_MD2
    725     BIO_puts(bio_out, "MD2\n");
    726 #endif
    727 #ifdef OPENSSL_NO_MD4
    728     BIO_puts(bio_out, "MD4\n");
    729 #endif
    730 #ifdef OPENSSL_NO_MD5
    731     BIO_puts(bio_out, "MD5\n");
    732 #endif
    733 #ifdef OPENSSL_NO_MDC2
    734     BIO_puts(bio_out, "MDC2\n");
    735 #endif
    736 #ifdef OPENSSL_NO_OCB
    737     BIO_puts(bio_out, "OCB\n");
    738 #endif
    739 #ifdef OPENSSL_NO_OCSP
    740     BIO_puts(bio_out, "OCSP\n");
    741 #endif
    742 #ifdef OPENSSL_NO_PSK
    743     BIO_puts(bio_out, "PSK\n");
    744 #endif
    745 #ifdef OPENSSL_NO_RC2
    746     BIO_puts(bio_out, "RC2\n");
    747 #endif
    748 #ifdef OPENSSL_NO_RC4
    749     BIO_puts(bio_out, "RC4\n");
    750 #endif
    751 #ifdef OPENSSL_NO_RC5
    752     BIO_puts(bio_out, "RC5\n");
    753 #endif
    754 #ifdef OPENSSL_NO_RMD160
    755     BIO_puts(bio_out, "RMD160\n");
    756 #endif
    757 #ifdef OPENSSL_NO_RSA
    758     BIO_puts(bio_out, "RSA\n");
    759 #endif
    760 #ifdef OPENSSL_NO_SCRYPT
    761     BIO_puts(bio_out, "SCRYPT\n");
    762 #endif
    763 #ifdef OPENSSL_NO_SCTP
    764     BIO_puts(bio_out, "SCTP\n");
    765 #endif
    766 #ifdef OPENSSL_NO_SEED
    767     BIO_puts(bio_out, "SEED\n");
    768 #endif
    769 #ifdef OPENSSL_NO_SM2
    770     BIO_puts(bio_out, "SM2\n");
    771 #endif
    772 #ifdef OPENSSL_NO_SM3
    773     BIO_puts(bio_out, "SM3\n");
    774 #endif
    775 #ifdef OPENSSL_NO_SM4
    776     BIO_puts(bio_out, "SM4\n");
    777 #endif
    778 #ifdef OPENSSL_NO_SOCK
    779     BIO_puts(bio_out, "SOCK\n");
    780 #endif
    781 #ifdef OPENSSL_NO_SRP
    782     BIO_puts(bio_out, "SRP\n");
    783 #endif
    784 #ifdef OPENSSL_NO_SRTP
    785     BIO_puts(bio_out, "SRTP\n");
    786 #endif
    787 #ifdef OPENSSL_NO_SSL3
    788     BIO_puts(bio_out, "SSL3\n");
    789 #endif
    790 #ifdef OPENSSL_NO_TLS1
    791     BIO_puts(bio_out, "TLS1\n");
    792 #endif
    793 #ifdef OPENSSL_NO_TLS1_1
    794     BIO_puts(bio_out, "TLS1_1\n");
    795 #endif
    796 #ifdef OPENSSL_NO_TLS1_2
    797     BIO_puts(bio_out, "TLS1_2\n");
    798 #endif
    799 #ifdef OPENSSL_NO_WHIRLPOOL
    800     BIO_puts(bio_out, "WHIRLPOOL\n");
    801 #endif
    802 #ifndef ZLIB
    803     BIO_puts(bio_out, "ZLIB\n");
    804 #endif
    805 }
    806 
    807 static LHASH_OF(FUNCTION) *prog_init(void)
    808 {
    809     static LHASH_OF(FUNCTION) *ret = NULL;
    810     static int prog_inited = 0;
    811     FUNCTION *f;
    812     size_t i;
    813 
    814     if (prog_inited)
    815         return ret;
    816 
    817     prog_inited = 1;
    818 
    819     /* Sort alphabetically within category. For nicer help displays. */
    820     for (i = 0, f = functions; f->name != NULL; ++f, ++i)
    821         ;
    822     qsort(functions, i, sizeof(*functions), SortFnByName);
    823 
    824     if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL)
    825         return NULL;
    826 
    827     for (f = functions; f->name != NULL; f++)
    828         (void)lh_FUNCTION_insert(ret, f);
    829     return ret;
    830 }
    831