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