X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fopenssl.c;h=7b0ccbcc092ee1cf70ede9af5788f6a30f4b3628;hp=539de761f0fe061ebae6ee55e841d959ae27b6e3;hb=7e998a0fdcbc59ef527ae84338439af75986c96a;hpb=e6b5c341b94d357b0158ad74b12edd51399a4b87 diff --git a/apps/openssl.c b/apps/openssl.c index 539de761f0..7b0ccbcc09 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -1,119 +1,19 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ +#include #include #include #include #include #include -#include +#include #include #include #include @@ -123,29 +23,12 @@ # include #endif #include -#ifdef OPENSSL_FIPS -# include -#endif -#define USE_SOCKETS /* needed for the _O_BINARY defs in the MS world */ -#include "s_apps.h" /* Needed to get the other O_xxx flags. */ #ifdef OPENSSL_SYS_VMS # include #endif -#define INCLUDE_FUNCTION_TABLE #include "apps.h" - - -#ifdef OPENSSL_NO_CAMELLIA -# define FORMAT "%-15s" -# define COLUMNS 5 -#else -# define FORMAT "%-18s" -# define COLUMNS 4 -#endif - -/* Special sentinel to exit the program. */ -#define EXIT_THE_PROGRAM (-1) +#include "progs.h" /* * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with @@ -155,396 +38,267 @@ */ static LHASH_OF(FUNCTION) *prog_init(void); static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); -static void list_pkey(void); -static void list_type(FUNC_TYPE ft); -static void list_disabled(void); char *default_config_file = NULL; -static CONF *config = NULL; BIO *bio_in = NULL; BIO *bio_out = NULL; BIO *bio_err = NULL; -static int apps_startup() +static void warn_deprecated(const FUNCTION *fp) +{ + if (fp->deprecated_version != NULL) + BIO_printf(bio_err, "The command %s was deprecated in version %s.", + fp->name, fp->deprecated_version); + else + BIO_printf(bio_err, "The command %s is deprecated.", fp->name); + if (strcmp(fp->deprecated_alternative, DEPRECATED_NO_ALTERNATIVE) != 0) + BIO_printf(bio_err, " Use '%s' instead.", fp->deprecated_alternative); + BIO_printf(bio_err, "\n"); +} + +static int apps_startup(void) { #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif - ERR_load_crypto_strings(); - ERR_load_SSL_strings(); - OPENSSL_load_builtin_modules(); - SSL_add_ssl_module(); -#ifndef OPENSSL_NO_ENGINE - ENGINE_load_builtin_engines(); -#endif - if (!app_load_modules(NULL)) { - ERR_print_errors(bio_err); - BIO_printf(bio_err, "Error loading default configuration\n"); + /* Set non-default library initialisation settings */ + if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN + | OPENSSL_INIT_LOAD_CONFIG, NULL)) return 0; - } - OpenSSL_add_all_algorithms(); - OpenSSL_add_ssl_algorithms(); setup_ui_method(); - /*SSL_library_init();*/ + return 1; } -static void apps_shutdown() +static void apps_shutdown(void) { -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif destroy_ui_method(); - CONF_modules_unload(1); -#ifndef OPENSSL_NO_COMP - COMP_zlib_cleanup(); - SSL_COMP_free_compression_methods(); -#endif - OBJ_cleanup(); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - RAND_cleanup(); - ERR_free_strings(); } -static char *make_config_name() + +#ifndef OPENSSL_NO_TRACE +typedef struct tracedata_st { + BIO *bio; + unsigned int ingroup:1; +} tracedata; + +static size_t internal_trace_cb(const char *buf, size_t cnt, + int category, int cmd, void *vdata) { - const char *t; - size_t len; - char *p; - - if ((t = getenv("OPENSSL_CONF")) != NULL) - return OPENSSL_strdup(t); - - t = X509_get_default_cert_area(); - len = strlen(t) + 1 + strlen(OPENSSL_CONF) + 1; - p = app_malloc(len, "config filename buffer"); - strcpy(p, t); -#ifndef OPENSSL_SYS_VMS - strcat(p, "/"); -#endif - strcat(p, OPENSSL_CONF); + int ret = 0; + tracedata *trace_data = vdata; + char buffer[256], *hex; + CRYPTO_THREAD_ID tid; + + switch (cmd) { + case OSSL_TRACE_CTRL_BEGIN: + if (!ossl_assert(!trace_data->ingroup)) + return 0; + trace_data->ingroup = 1; + + tid = CRYPTO_THREAD_get_current_id(); + hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid)); + BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ", + hex == NULL ? "" : hex, + OSSL_trace_get_category_name(category)); + OPENSSL_free(hex); + BIO_set_prefix(trace_data->bio, buffer); + break; + case OSSL_TRACE_CTRL_WRITE: + if (!ossl_assert(trace_data->ingroup)) + return 0; + + ret = BIO_write(trace_data->bio, buf, cnt); + break; + case OSSL_TRACE_CTRL_END: + if (!ossl_assert(trace_data->ingroup)) + return 0; + trace_data->ingroup = 0; + + BIO_set_prefix(trace_data->bio, NULL); + + break; + } - return p; + return ret < 0 ? 0 : ret; } -static void lock_dbg_cb(int mode, int type, const char *file, int line) +DEFINE_STACK_OF(tracedata) +static STACK_OF(tracedata) *trace_data_stack; + +static void tracedata_free(tracedata *data) { - static int modes[CRYPTO_NUM_LOCKS]; - const char *errstr = NULL; - int rw = mode & (CRYPTO_READ | CRYPTO_WRITE); + BIO_free_all(data->bio); + OPENSSL_free(data); +} - if (rw != CRYPTO_READ && rw != CRYPTO_WRITE) { - errstr = "invalid mode"; - goto err; - } +static STACK_OF(tracedata) *trace_data_stack; - if (type < 0 || type >= CRYPTO_NUM_LOCKS) { - errstr = "type out of bounds"; - goto err; - } +static void cleanup_trace(void) +{ + sk_tracedata_pop_free(trace_data_stack, tracedata_free); +} - if (mode & CRYPTO_LOCK) { - if (modes[type]) { - errstr = "already locked"; - /* must not happen in a single-threaded program --> deadlock! */ - goto err; - } - modes[type] = rw; - } else if (mode & CRYPTO_UNLOCK) { - if (!modes[type]) { - errstr = "not locked"; - goto err; - } +static void setup_trace_category(int category) +{ + BIO *channel; + tracedata *trace_data; - if (modes[type] != rw) { - errstr = (rw == CRYPTO_READ) ? - "CRYPTO_r_unlock on write lock" : - "CRYPTO_w_unlock on read lock"; - } + if (OSSL_trace_enabled(category)) + return; - modes[type] = 0; - } else { - errstr = "invalid mode"; - goto err; - } + channel = BIO_push(BIO_new(BIO_f_prefix()), dup_bio_err(FORMAT_TEXT)); + trace_data = OPENSSL_zalloc(sizeof(*trace_data)); - err: - if (errstr) { - BIO_printf(bio_err, - "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n", - errstr, mode, type, file, line); + if (trace_data == NULL + || (trace_data->bio = channel) == NULL + || OSSL_trace_set_callback(category, internal_trace_cb, + trace_data) == 0 + || sk_tracedata_push(trace_data_stack, trace_data) == 0) { + + fprintf(stderr, + "warning: unable to setup trace callback for category '%s'.\n", + OSSL_trace_get_category_name(category)); + + OSSL_trace_set_callback(category, NULL, NULL); + BIO_free_all(channel); } } -#if defined( OPENSSL_SYS_VMS) -extern char **copy_argv(int *argc, char **argv); -#endif +static void setup_trace(const char *str) +{ + char *val; + + /* + * We add this handler as early as possible to ensure it's executed + * as late as possible, i.e. after the TRACE code has done its cleanup + * (which happens last in OPENSSL_cleanup). + */ + atexit(cleanup_trace); + + trace_data_stack = sk_tracedata_new_null(); + val = OPENSSL_strdup(str); + + if (val != NULL) { + char *valp = val; + char *item; + + for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) { + int category = OSSL_trace_get_category_num(item); + + if (category == OSSL_TRACE_CATEGORY_ALL) { + while (++category < OSSL_TRACE_CATEGORY_NUM) + setup_trace_category(category); + break; + } else if (category > 0) { + setup_trace_category(category); + } else { + fprintf(stderr, + "warning: unknown trace category: '%s'.\n", item); + } + } + } + + OPENSSL_free(val); +} +#endif /* OPENSSL_NO_TRACE */ int main(int argc, char *argv[]) { FUNCTION f, *fp; LHASH_OF(FUNCTION) *prog = NULL; - char **copied_argv = NULL; - char *p, *pname; - char buf[1024]; - const char *prompt; + char *pname; ARGS arg; - int first, n, i, ret = 0; + int ret = 0; arg.argv = NULL; arg.size = 0; /* Set up some of the environment. */ - default_config_file = make_config_name(); bio_in = dup_bio_in(FORMAT_TEXT); bio_out = dup_bio_out(FORMAT_TEXT); - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); + bio_err = dup_bio_err(FORMAT_TEXT); -#if defined( OPENSSL_SYS_VMS) - copied_argv = argv = copy_argv(&argc, argv); +#if defined(OPENSSL_SYS_VMS) && defined(__DECC) + argv = copy_argv(&argc, argv); +#elif defined(_WIN32) + /* + * Replace argv[] with UTF-8 encoded strings. + */ + win32_utf8argv(&argc, &argv); #endif - p = getenv("OPENSSL_DEBUG_MEMORY"); - if (p != NULL && strcmp(p, "on") == 0) - CRYPTO_set_mem_debug(1); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - CRYPTO_set_locking_callback(lock_dbg_cb); - - if (getenv("OPENSSL_FIPS")) { -#ifdef OPENSSL_FIPS - if (!FIPS_mode_set(1)) { - ERR_load_crypto_strings(); - ERR_print_errors(bio_err); - return 1; - } -#else - BIO_printf(bio_err, "FIPS mode not supported.\n"); - return 1; +#ifndef OPENSSL_NO_TRACE + setup_trace(getenv("OPENSSL_TRACE")); #endif - } - if (!apps_startup()) + if (!apps_startup()) { + BIO_printf(bio_err, + "FATAL: Startup failure (dev note: apps_startup() failed)\n"); + ERR_print_errors(bio_err); + ret = 1; goto end; + } prog = prog_init(); + if (prog == NULL) { + BIO_printf(bio_err, + "FATAL: Startup failure (dev note: prog_init() failed)\n"); + ERR_print_errors(bio_err); + ret = 1; + goto end; + } pname = opt_progname(argv[0]); + default_config_file = CONF_get1_default_config_file(); + if (default_config_file == NULL) + app_bail_out("%s: could not get default config file\n", pname); + /* first check the program name */ f.name = pname; fp = lh_FUNCTION_retrieve(prog, &f); - if (fp != NULL) { - argv[0] = pname; - ret = fp->func(argc, argv); - goto end; - } - - /* If there is stuff on the command line, run with that. */ - if (argc != 1) { + if (fp == NULL) { + /* We assume we've been called as 'openssl cmd' */ argc--; argv++; - ret = do_cmd(prog, argc, argv); - if (ret < 0) - ret = 0; - goto end; } - /* ok, lets enter interactive mode */ - for (;;) { - ret = 0; - /* Read a line, continue reading if line ends with \ */ - for (p = buf, n = sizeof buf, i = 0, first = 1; n > 0; first = 0) { - prompt = first ? "OpenSSL> " : "> "; - p[0] = '\0'; -#ifndef READLINE - fputs(prompt, stdout); - fflush(stdout); - if (!fgets(p, n, stdin)) - goto end; - if (p[0] == '\0') - goto end; - i = strlen(p); - if (i <= 1) - break; - if (p[i - 2] != '\\') - break; - i -= 2; - p += i; - n -= i; -#else - { - extern char *readline(const char *); - extern void add_history(const char *cp); - char *text; - - char *text = readline(prompt); - if (text == NULL) - goto end; - i = strlen(text); - if (i == 0 || i > n) - break; - if (text[i - 1] != '\\') { - p += strlen(strcpy(p, text)); - free(text); - add_history(buf); - break; - } - - text[i - 1] = '\0'; - p += strlen(strcpy(p, text)); - free(text); - n -= i; - } -#endif - } - - if (!chopup_args(&arg, buf)) { - BIO_printf(bio_err, "Can't parse (no memory?)\n"); - break; - } + /* If there's a command, run with that, otherwise "help". */ + ret = argc > 0 + ? do_cmd(prog, argc, argv) + : help_main(argc, argv); - ret = do_cmd(prog, arg.argc, arg.argv); - if (ret == EXIT_THE_PROGRAM) { - ret = 0; - goto end; - } - if (ret != 0) - BIO_printf(bio_err, "error in %s\n", arg.argv[0]); - (void)BIO_flush(bio_out); - (void)BIO_flush(bio_err); - } - ret = 1; end: - OPENSSL_free(copied_argv); + app_providers_cleanup(); OPENSSL_free(default_config_file); - NCONF_free(config); - config = NULL; lh_FUNCTION_free(prog); OPENSSL_free(arg.argv); + app_RAND_write(); BIO_free(bio_in); BIO_free_all(bio_out); apps_shutdown(); -#ifndef OPENSSL_NO_CRYPTO_MDEBUG - CRYPTO_mem_leaks(bio_err); -#endif BIO_free(bio_err); - return (ret); + EXIT(ret); } -OPTIONS exit_options[] = { - {NULL} -}; +typedef enum HELP_CHOICE { + OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP +} HELP_CHOICE; -static void list_cipher_fn(const EVP_CIPHER *c, - const char *from, const char *to, void *arg) -{ - if (c) - BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); - else { - if (!from) - from = ""; - if (!to) - to = ""; - BIO_printf(arg, "%s => %s\n", from, to); - } -} +const OPTIONS help_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: help [options] [command]\n"}, -static void list_md_fn(const EVP_MD *m, - const char *from, const char *to, void *arg) -{ - if (m) - BIO_printf(arg, "%s\n", EVP_MD_name(m)); - else { - if (!from) - from = ""; - if (!to) - to = ""; - BIO_printf((BIO *)arg, "%s => %s\n", from, to); - } -} + OPT_SECTION("General"), + {"help", OPT_hHELP, '-', "Display this summary"}, -/* Unified enum for help and list commands. */ -typedef enum HELPLIST_CHOICE { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, - OPT_COMMANDS, OPT_DIGEST_COMMANDS, - OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, - OPT_PK_ALGORITHMS, OPT_DISABLED -} HELPLIST_CHOICE; - -OPTIONS list_options[] = { - {"help", OPT_HELP, '-', "Display this summary"}, - {"commands", OPT_COMMANDS, '-', "List of standard commands"}, - {"digest-commands", OPT_DIGEST_COMMANDS, '-', - "List of message digest commands"}, - {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-', - "List of message digest algorithms"}, - {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"}, - {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', - "List of cipher algorithms"}, - {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', - "List of public key algorithms"}, - {"disabled", OPT_DISABLED, '-', - "List of disabled features"}, + OPT_PARAMETERS(), + {"command", 0, 0, "Name of command to display help (optional)"}, {NULL} }; -int list_main(int argc, char **argv) -{ - char *prog; - HELPLIST_CHOICE o; - int done = 0; - - prog = opt_init(argc, argv, list_options); - while ((o = opt_next()) != OPT_EOF) { - switch (o) { - case OPT_EOF: /* Never hit, but suppresses warning */ - case OPT_ERR: - BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - return 1; - case OPT_HELP: - opt_help(list_options); - break; - case OPT_COMMANDS: - list_type(FT_general); - break; - case OPT_DIGEST_COMMANDS: - list_type(FT_md); - break; - case OPT_DIGEST_ALGORITHMS: - EVP_MD_do_all_sorted(list_md_fn, bio_out); - break; - case OPT_CIPHER_COMMANDS: - list_type(FT_cipher); - break; - case OPT_CIPHER_ALGORITHMS: - EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out); - break; - case OPT_PK_ALGORITHMS: - list_pkey(); - break; - case OPT_DISABLED: - list_disabled(); - break; - } - done = 1; - } - - if (!done) { - BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - return 1; - } - - return 0; -} - -OPTIONS help_options[] = { - {"help", OPT_HELP, '-', "Display this summary"}, - {NULL} -}; int help_main(int argc, char **argv) { @@ -552,33 +306,42 @@ int help_main(int argc, char **argv) int i, nl; FUNC_TYPE tp; char *prog; - HELPLIST_CHOICE o; + HELP_CHOICE o; + DISPLAY_COLUMNS dc; prog = opt_init(argc, argv, help_options); - while ((o = opt_next()) != OPT_EOF) { + while ((o = opt_next()) != OPT_hEOF) { switch (o) { - default: + case OPT_hERR: + case OPT_hEOF: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); return 1; - case OPT_HELP: + case OPT_hHELP: opt_help(help_options); return 0; } } - argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 0) { + if (opt_num_rest() == 1) { + char *new_argv[3]; + + new_argv[0] = opt_rest()[0]; + new_argv[1] = "--help"; + new_argv[2] = NULL; + return do_cmd(prog_init(), 2, new_argv); + } + if (opt_num_rest() != 0) { BIO_printf(bio_err, "Usage: %s\n", prog); return 1; } - BIO_printf(bio_err, "\nStandard commands"); + calculate_columns(functions, &dc); + BIO_printf(bio_err, "Standard commands"); i = 0; tp = FT_none; for (fp = functions; fp->name != NULL; fp++) { nl = 0; - if (((i++) % COLUMNS) == 0) { + if (i++ % dc.columns == 0) { BIO_printf(bio_err, "\n"); nl = 1; } @@ -596,37 +359,18 @@ int help_main(int argc, char **argv) "\nCipher commands (see the `enc' command for more details)\n"); } } - BIO_printf(bio_err, FORMAT, fp->name); + BIO_printf(bio_err, "%-*s", dc.width, fp->name); } BIO_printf(bio_err, "\n\n"); return 0; } -int exit_main(int argc, char **argv) -{ - return EXIT_THE_PROGRAM; -} - -static void list_type(FUNC_TYPE ft) -{ - FUNCTION *fp; - int i = 0; - - for (fp = functions; fp->name != NULL; fp++) - if (fp->type == ft) { - if ((i++ % COLUMNS) == 0) - BIO_printf(bio_out, "\n"); - BIO_printf(bio_out, FORMAT, fp->name); - } - BIO_printf(bio_out, "\n"); -} - static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) { FUNCTION f, *fp; if (argc <= 0 || argv[0] == NULL) - return (0); + return 0; f.name = argv[0]; fp = lh_FUNCTION_retrieve(prog, &f); if (fp == NULL) { @@ -641,7 +385,9 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) } } if (fp != NULL) { - return (fp->func(argc, argv)); + if (fp->deprecated_alternative != NULL) + warn_deprecated(fp); + return fp->func(argc, argv); } if ((strncmp(argv[0], "no-", 3)) == 0) { /* @@ -651,48 +397,15 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) f.name = argv[0] + 3; if (lh_FUNCTION_retrieve(prog, &f) == NULL) { BIO_printf(bio_out, "%s\n", argv[0]); - return (0); + return 0; } BIO_printf(bio_out, "%s\n", argv[0] + 3); return 1; } - if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || - strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) - /* Special value to mean "exit the program. */ - return EXIT_THE_PROGRAM; BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", argv[0]); - return (1); -} - -static void list_pkey(void) -{ - int i; - - for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { - const EVP_PKEY_ASN1_METHOD *ameth; - int pkey_id, pkey_base_id, pkey_flags; - const char *pinfo, *pem_str; - ameth = EVP_PKEY_asn1_get0(i); - EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, - &pinfo, &pem_str, ameth); - if (pkey_flags & ASN1_PKEY_ALIAS) { - BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id)); - BIO_printf(bio_out, "\tAlias for: %s\n", - OBJ_nid2ln(pkey_base_id)); - } else { - BIO_printf(bio_out, "Name: %s\n", pinfo); - BIO_printf(bio_out, "\tType: %s Algorithm\n", - pkey_flags & ASN1_PKEY_DYNAMIC ? - "External" : "Builtin"); - BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); - if (pem_str == NULL) - pem_str = "(none)"; - BIO_printf(bio_out, "\tPEM string: %s\n", pem_str); - } - - } + return 1; } static int function_cmp(const FUNCTION * a, const FUNCTION * b) @@ -700,15 +413,11 @@ static int function_cmp(const FUNCTION * a, const FUNCTION * b) return strncmp(a->name, b->name, 8); } -static IMPLEMENT_LHASH_COMP_FN(function, FUNCTION) - static unsigned long function_hash(const FUNCTION * a) { - return lh_strhash(a->name); + return OPENSSL_LH_strhash(a->name); } -static IMPLEMENT_LHASH_HASH_FN(function, FUNCTION) - static int SortFnByName(const void *_f1, const void *_f2) { const FUNCTION *f1 = _f1; @@ -719,151 +428,27 @@ static int SortFnByName(const void *_f1, const void *_f2) return strcmp(f1->name, f2->name); } -static void list_disabled(void) -{ - BIO_puts(bio_out, "Disabled algorithms:\n"); -#ifdef OPENSSL_NO_AES - BIO_puts(bio_out, "AES\n"); -#endif -#ifdef OPENSSL_NO_BF - BIO_puts(bio_out, "BF\n"); -#endif -#ifdef OPENSSL_NO_CAMELLIA - BIO_puts(bio_out, "CAMELLIA\n"); -#endif -#ifdef OPENSSL_NO_CAST - BIO_puts(bio_out, "CAST\n"); -#endif -#ifdef OPENSSL_NO_CMAC - BIO_puts(bio_out, "CMAC\n"); -#endif -#ifdef OPENSSL_NO_CMS - BIO_puts(bio_out, "CMS\n"); -#endif -#ifdef OPENSSL_NO_COMP - BIO_puts(bio_out, "COMP\n"); -#endif -#ifdef OPENSSL_NO_DES - BIO_puts(bio_out, "DES\n"); -#endif -#ifdef OPENSSL_NO_DGRAM - BIO_puts(bio_out, "DGRAM\n"); -#endif -#ifdef OPENSSL_NO_DH - BIO_puts(bio_out, "DH\n"); -#endif -#ifdef OPENSSL_NO_DSA - BIO_puts(bio_out, "DSA\n"); -#endif -#if defined(OPENSSL_NO_DTLS) - BIO_puts(bio_out, "DTLS\n"); -#endif -#ifdef OPENSSL_NO_EC - BIO_puts(bio_out, "EC\n"); -#endif -#ifdef OPENSSL_NO_EC2M - BIO_puts(bio_out, "EC2M\n"); -#endif -#ifdef OPENSSL_NO_ENGINE - BIO_puts(bio_out, "ENGINE\n"); -#endif -#ifdef OPENSSL_NO_GOST - BIO_puts(bio_out, "GOST\n"); -#endif -#ifdef OPENSSL_NO_HMAC - BIO_puts(bio_out, "HMAC\n"); -#endif -#ifdef OPENSSL_NO_IDEA - BIO_puts(bio_out, "IDEA\n"); -#endif -#ifdef OPENSSL_NO_JPAKE - BIO_puts(bio_out, "JPAKE\n"); -#endif -#ifdef OPENSSL_NO_MD2 - BIO_puts(bio_out, "MD2\n"); -#endif -#ifdef OPENSSL_NO_MD4 - BIO_puts(bio_out, "MD4\n"); -#endif -#ifdef OPENSSL_NO_MD5 - BIO_puts(bio_out, "MD5\n"); -#endif -#ifdef OPENSSL_NO_MDC2 - BIO_puts(bio_out, "MDC2\n"); -#endif -#ifdef OPENSSL_NO_OCB - BIO_puts(bio_out, "OCB\n"); -#endif -#ifdef OPENSSL_NO_OCSP - BIO_puts(bio_out, "OCSP\n"); -#endif -#ifdef OPENSSL_NO_PSK - BIO_puts(bio_out, "PSK\n"); -#endif -#ifdef OPENSSL_NO_RC2 - BIO_puts(bio_out, "RC2\n"); -#endif -#ifdef OPENSSL_NO_RC4 - BIO_puts(bio_out, "RC4\n"); -#endif -#ifdef OPENSSL_NO_RC5 - BIO_puts(bio_out, "RC5\n"); -#endif -#ifdef OPENSSL_NO_RMD160 - BIO_puts(bio_out, "RMD160\n"); -#endif -#ifdef OPENSSL_NO_RSA - BIO_puts(bio_out, "RSA\n"); -#endif -#ifdef OPENSSL_NO_SCRYPT - BIO_puts(bio_out, "SCRYPT\n"); -#endif -#ifdef OPENSSL_NO_SCT - BIO_puts(bio_out, "SCT\n"); -#endif -#ifdef OPENSSL_NO_SCTP - BIO_puts(bio_out, "SCTP\n"); -#endif -#ifdef OPENSSL_NO_SEED - BIO_puts(bio_out, "SEED\n"); -#endif -#ifdef OPENSSL_NO_SHA - BIO_puts(bio_out, "SHA\n"); -#endif -#ifdef OPENSSL_NO_SOCK - BIO_puts(bio_out, "SOCK\n"); -#endif -#ifdef OPENSSL_NO_SRP - BIO_puts(bio_out, "SRP\n"); -#endif -#ifdef OPENSSL_NO_SRTP - BIO_puts(bio_out, "SRTP\n"); -#endif -#ifdef OPENSSL_NO_SSL3 - BIO_puts(bio_out, "SSL3\n"); -#endif -#ifdef OPENSSL_NO_WHIRLPOOL - BIO_puts(bio_out, "WHIRLPOOL\n"); -#endif -#ifndef ZLIB - BIO_puts(bio_out, "ZLIB\n"); -#endif -} - static LHASH_OF(FUNCTION) *prog_init(void) { - LHASH_OF(FUNCTION) *ret; + static LHASH_OF(FUNCTION) *ret = NULL; + static int prog_inited = 0; FUNCTION *f; size_t i; + if (prog_inited) + return ret; + + prog_inited = 1; + /* Sort alphabetically within category. For nicer help displays. */ - for (i = 0, f = functions; f->name != NULL; ++f, ++i) ; + for (i = 0, f = functions; f->name != NULL; ++f, ++i) + ; qsort(functions, i, sizeof(*functions), SortFnByName); - if ((ret = lh_FUNCTION_new()) == NULL) - return (NULL); + if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL) + return NULL; for (f = functions; f->name != NULL; f++) (void)lh_FUNCTION_insert(ret, f); - return (ret); + return ret; }