1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci#include <stdlib.h> 13e1051a39Sopenharmony_ci#include <openssl/bio.h> 14e1051a39Sopenharmony_ci#include <openssl/crypto.h> 15e1051a39Sopenharmony_ci#include <openssl/trace.h> 16e1051a39Sopenharmony_ci#include <openssl/lhash.h> 17e1051a39Sopenharmony_ci#include <openssl/conf.h> 18e1051a39Sopenharmony_ci#include <openssl/x509.h> 19e1051a39Sopenharmony_ci#include <openssl/pem.h> 20e1051a39Sopenharmony_ci#include <openssl/ssl.h> 21e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 22e1051a39Sopenharmony_ci# include <openssl/engine.h> 23e1051a39Sopenharmony_ci#endif 24e1051a39Sopenharmony_ci#include <openssl/err.h> 25e1051a39Sopenharmony_ci/* Needed to get the other O_xxx flags. */ 26e1051a39Sopenharmony_ci#ifdef OPENSSL_SYS_VMS 27e1051a39Sopenharmony_ci# include <unixio.h> 28e1051a39Sopenharmony_ci#endif 29e1051a39Sopenharmony_ci#include "apps.h" 30e1051a39Sopenharmony_ci#include "progs.h" 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci/* 33e1051a39Sopenharmony_ci * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with 34e1051a39Sopenharmony_ci * the base prototypes (we cast each variable inside the function to the 35e1051a39Sopenharmony_ci * required type of "FUNCTION*"). This removes the necessity for 36e1051a39Sopenharmony_ci * macro-generated wrapper functions. 37e1051a39Sopenharmony_ci */ 38e1051a39Sopenharmony_cistatic LHASH_OF(FUNCTION) *prog_init(void); 39e1051a39Sopenharmony_cistatic int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); 40e1051a39Sopenharmony_cichar *default_config_file = NULL; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ciBIO *bio_in = NULL; 43e1051a39Sopenharmony_ciBIO *bio_out = NULL; 44e1051a39Sopenharmony_ciBIO *bio_err = NULL; 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_cistatic void warn_deprecated(const FUNCTION *fp) 47e1051a39Sopenharmony_ci{ 48e1051a39Sopenharmony_ci if (fp->deprecated_version != NULL) 49e1051a39Sopenharmony_ci BIO_printf(bio_err, "The command %s was deprecated in version %s.", 50e1051a39Sopenharmony_ci fp->name, fp->deprecated_version); 51e1051a39Sopenharmony_ci else 52e1051a39Sopenharmony_ci BIO_printf(bio_err, "The command %s is deprecated.", fp->name); 53e1051a39Sopenharmony_ci if (strcmp(fp->deprecated_alternative, DEPRECATED_NO_ALTERNATIVE) != 0) 54e1051a39Sopenharmony_ci BIO_printf(bio_err, " Use '%s' instead.", fp->deprecated_alternative); 55e1051a39Sopenharmony_ci BIO_printf(bio_err, "\n"); 56e1051a39Sopenharmony_ci} 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_cistatic int apps_startup(void) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci const char *use_libctx = NULL; 61e1051a39Sopenharmony_ci#ifdef SIGPIPE 62e1051a39Sopenharmony_ci signal(SIGPIPE, SIG_IGN); 63e1051a39Sopenharmony_ci#endif 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci /* Set non-default library initialisation settings */ 66e1051a39Sopenharmony_ci if (!OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN 67e1051a39Sopenharmony_ci | OPENSSL_INIT_LOAD_CONFIG, NULL)) 68e1051a39Sopenharmony_ci return 0; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci (void)setup_ui_method(); 71e1051a39Sopenharmony_ci (void)setup_engine_loader(); 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci /* 74e1051a39Sopenharmony_ci * NOTE: This is an undocumented feature required for testing only. 75e1051a39Sopenharmony_ci * There are no guarantees that it will exist in future builds. 76e1051a39Sopenharmony_ci */ 77e1051a39Sopenharmony_ci use_libctx = getenv("OPENSSL_TEST_LIBCTX"); 78e1051a39Sopenharmony_ci if (use_libctx != NULL) { 79e1051a39Sopenharmony_ci /* Set this to "1" to create a global libctx */ 80e1051a39Sopenharmony_ci if (strcmp(use_libctx, "1") == 0) { 81e1051a39Sopenharmony_ci if (app_create_libctx() == NULL) 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci } 84e1051a39Sopenharmony_ci } 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci return 1; 87e1051a39Sopenharmony_ci} 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_cistatic void apps_shutdown(void) 90e1051a39Sopenharmony_ci{ 91e1051a39Sopenharmony_ci app_providers_cleanup(); 92e1051a39Sopenharmony_ci OSSL_LIB_CTX_free(app_get0_libctx()); 93e1051a39Sopenharmony_ci destroy_engine_loader(); 94e1051a39Sopenharmony_ci destroy_ui_method(); 95e1051a39Sopenharmony_ci} 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci 98e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_TRACE 99e1051a39Sopenharmony_citypedef struct tracedata_st { 100e1051a39Sopenharmony_ci BIO *bio; 101e1051a39Sopenharmony_ci unsigned int ingroup:1; 102e1051a39Sopenharmony_ci} tracedata; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_cistatic size_t internal_trace_cb(const char *buf, size_t cnt, 105e1051a39Sopenharmony_ci int category, int cmd, void *vdata) 106e1051a39Sopenharmony_ci{ 107e1051a39Sopenharmony_ci int ret = 0; 108e1051a39Sopenharmony_ci tracedata *trace_data = vdata; 109e1051a39Sopenharmony_ci char buffer[256], *hex; 110e1051a39Sopenharmony_ci CRYPTO_THREAD_ID tid; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci switch (cmd) { 113e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_BEGIN: 114e1051a39Sopenharmony_ci if (trace_data->ingroup) { 115e1051a39Sopenharmony_ci BIO_printf(bio_err, "ERROR: tracing already started\n"); 116e1051a39Sopenharmony_ci return 0; 117e1051a39Sopenharmony_ci } 118e1051a39Sopenharmony_ci trace_data->ingroup = 1; 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci tid = CRYPTO_THREAD_get_current_id(); 121e1051a39Sopenharmony_ci hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid)); 122e1051a39Sopenharmony_ci BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ", 123e1051a39Sopenharmony_ci hex == NULL ? "<null>" : hex, 124e1051a39Sopenharmony_ci OSSL_trace_get_category_name(category)); 125e1051a39Sopenharmony_ci OPENSSL_free(hex); 126e1051a39Sopenharmony_ci BIO_set_prefix(trace_data->bio, buffer); 127e1051a39Sopenharmony_ci break; 128e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_WRITE: 129e1051a39Sopenharmony_ci if (!trace_data->ingroup) { 130e1051a39Sopenharmony_ci BIO_printf(bio_err, "ERROR: writing when tracing not started\n"); 131e1051a39Sopenharmony_ci return 0; 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci ret = BIO_write(trace_data->bio, buf, cnt); 135e1051a39Sopenharmony_ci break; 136e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_END: 137e1051a39Sopenharmony_ci if (!trace_data->ingroup) { 138e1051a39Sopenharmony_ci BIO_printf(bio_err, "ERROR: finishing when tracing not started\n"); 139e1051a39Sopenharmony_ci return 0; 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci trace_data->ingroup = 0; 142e1051a39Sopenharmony_ci 143e1051a39Sopenharmony_ci BIO_set_prefix(trace_data->bio, NULL); 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci break; 146e1051a39Sopenharmony_ci } 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci return ret < 0 ? 0 : ret; 149e1051a39Sopenharmony_ci} 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ciDEFINE_STACK_OF(tracedata) 152e1051a39Sopenharmony_cistatic STACK_OF(tracedata) *trace_data_stack; 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_cistatic void tracedata_free(tracedata *data) 155e1051a39Sopenharmony_ci{ 156e1051a39Sopenharmony_ci BIO_free_all(data->bio); 157e1051a39Sopenharmony_ci OPENSSL_free(data); 158e1051a39Sopenharmony_ci} 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_cistatic STACK_OF(tracedata) *trace_data_stack; 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_cistatic void cleanup_trace(void) 163e1051a39Sopenharmony_ci{ 164e1051a39Sopenharmony_ci sk_tracedata_pop_free(trace_data_stack, tracedata_free); 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_cistatic void setup_trace_category(int category) 168e1051a39Sopenharmony_ci{ 169e1051a39Sopenharmony_ci BIO *channel; 170e1051a39Sopenharmony_ci tracedata *trace_data; 171e1051a39Sopenharmony_ci BIO *bio = NULL; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci if (OSSL_trace_enabled(category)) 174e1051a39Sopenharmony_ci return; 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ci bio = BIO_new(BIO_f_prefix()); 177e1051a39Sopenharmony_ci channel = BIO_push(bio, dup_bio_err(FORMAT_TEXT)); 178e1051a39Sopenharmony_ci trace_data = OPENSSL_zalloc(sizeof(*trace_data)); 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci if (trace_data == NULL 181e1051a39Sopenharmony_ci || bio == NULL 182e1051a39Sopenharmony_ci || (trace_data->bio = channel) == NULL 183e1051a39Sopenharmony_ci || OSSL_trace_set_callback(category, internal_trace_cb, 184e1051a39Sopenharmony_ci trace_data) == 0 185e1051a39Sopenharmony_ci || sk_tracedata_push(trace_data_stack, trace_data) == 0) { 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci fprintf(stderr, 188e1051a39Sopenharmony_ci "warning: unable to setup trace callback for category '%s'.\n", 189e1051a39Sopenharmony_ci OSSL_trace_get_category_name(category)); 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci OSSL_trace_set_callback(category, NULL, NULL); 192e1051a39Sopenharmony_ci BIO_free_all(channel); 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci} 195e1051a39Sopenharmony_ci 196e1051a39Sopenharmony_cistatic void setup_trace(const char *str) 197e1051a39Sopenharmony_ci{ 198e1051a39Sopenharmony_ci char *val; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci /* 201e1051a39Sopenharmony_ci * We add this handler as early as possible to ensure it's executed 202e1051a39Sopenharmony_ci * as late as possible, i.e. after the TRACE code has done its cleanup 203e1051a39Sopenharmony_ci * (which happens last in OPENSSL_cleanup). 204e1051a39Sopenharmony_ci */ 205e1051a39Sopenharmony_ci atexit(cleanup_trace); 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci trace_data_stack = sk_tracedata_new_null(); 208e1051a39Sopenharmony_ci val = OPENSSL_strdup(str); 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci if (val != NULL) { 211e1051a39Sopenharmony_ci char *valp = val; 212e1051a39Sopenharmony_ci char *item; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) { 215e1051a39Sopenharmony_ci int category = OSSL_trace_get_category_num(item); 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if (category == OSSL_TRACE_CATEGORY_ALL) { 218e1051a39Sopenharmony_ci while (++category < OSSL_TRACE_CATEGORY_NUM) 219e1051a39Sopenharmony_ci setup_trace_category(category); 220e1051a39Sopenharmony_ci break; 221e1051a39Sopenharmony_ci } else if (category > 0) { 222e1051a39Sopenharmony_ci setup_trace_category(category); 223e1051a39Sopenharmony_ci } else { 224e1051a39Sopenharmony_ci fprintf(stderr, 225e1051a39Sopenharmony_ci "warning: unknown trace category: '%s'.\n", item); 226e1051a39Sopenharmony_ci } 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci OPENSSL_free(val); 231e1051a39Sopenharmony_ci} 232e1051a39Sopenharmony_ci#endif /* OPENSSL_NO_TRACE */ 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_cistatic char *help_argv[] = { "help", NULL }; 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ciint main(int argc, char *argv[]) 237e1051a39Sopenharmony_ci{ 238e1051a39Sopenharmony_ci FUNCTION f, *fp; 239e1051a39Sopenharmony_ci LHASH_OF(FUNCTION) *prog = NULL; 240e1051a39Sopenharmony_ci char *pname; 241e1051a39Sopenharmony_ci const char *fname; 242e1051a39Sopenharmony_ci ARGS arg; 243e1051a39Sopenharmony_ci int global_help = 0; 244e1051a39Sopenharmony_ci int ret = 0; 245e1051a39Sopenharmony_ci 246e1051a39Sopenharmony_ci arg.argv = NULL; 247e1051a39Sopenharmony_ci arg.size = 0; 248e1051a39Sopenharmony_ci 249e1051a39Sopenharmony_ci /* Set up some of the environment. */ 250e1051a39Sopenharmony_ci bio_in = dup_bio_in(FORMAT_TEXT); 251e1051a39Sopenharmony_ci bio_out = dup_bio_out(FORMAT_TEXT); 252e1051a39Sopenharmony_ci bio_err = dup_bio_err(FORMAT_TEXT); 253e1051a39Sopenharmony_ci 254e1051a39Sopenharmony_ci#if defined(OPENSSL_SYS_VMS) && defined(__DECC) 255e1051a39Sopenharmony_ci argv = copy_argv(&argc, argv); 256e1051a39Sopenharmony_ci#elif defined(_WIN32) 257e1051a39Sopenharmony_ci /* Replace argv[] with UTF-8 encoded strings. */ 258e1051a39Sopenharmony_ci win32_utf8argv(&argc, &argv); 259e1051a39Sopenharmony_ci#endif 260e1051a39Sopenharmony_ci 261e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_TRACE 262e1051a39Sopenharmony_ci setup_trace(getenv("OPENSSL_TRACE")); 263e1051a39Sopenharmony_ci#endif 264e1051a39Sopenharmony_ci 265e1051a39Sopenharmony_ci if ((fname = "apps_startup", !apps_startup()) 266e1051a39Sopenharmony_ci || (fname = "prog_init", (prog = prog_init()) == NULL)) { 267e1051a39Sopenharmony_ci BIO_printf(bio_err, 268e1051a39Sopenharmony_ci "FATAL: Startup failure (dev note: %s()) for %s\n", 269e1051a39Sopenharmony_ci fname, argv[0]); 270e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 271e1051a39Sopenharmony_ci ret = 1; 272e1051a39Sopenharmony_ci goto end; 273e1051a39Sopenharmony_ci } 274e1051a39Sopenharmony_ci pname = opt_progname(argv[0]); 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci default_config_file = CONF_get1_default_config_file(); 277e1051a39Sopenharmony_ci if (default_config_file == NULL) 278e1051a39Sopenharmony_ci app_bail_out("%s: could not get default config file\n", pname); 279e1051a39Sopenharmony_ci 280e1051a39Sopenharmony_ci /* first check the program name */ 281e1051a39Sopenharmony_ci f.name = pname; 282e1051a39Sopenharmony_ci fp = lh_FUNCTION_retrieve(prog, &f); 283e1051a39Sopenharmony_ci if (fp == NULL) { 284e1051a39Sopenharmony_ci /* We assume we've been called as 'openssl ...' */ 285e1051a39Sopenharmony_ci global_help = argc > 1 286e1051a39Sopenharmony_ci && (strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 287e1051a39Sopenharmony_ci || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0); 288e1051a39Sopenharmony_ci argc--; 289e1051a39Sopenharmony_ci argv++; 290e1051a39Sopenharmony_ci opt_appname(argc == 1 || global_help ? "help" : argv[0]); 291e1051a39Sopenharmony_ci } else { 292e1051a39Sopenharmony_ci argv[0] = pname; 293e1051a39Sopenharmony_ci } 294e1051a39Sopenharmony_ci 295e1051a39Sopenharmony_ci /* If there's a command, run with that, otherwise "help". */ 296e1051a39Sopenharmony_ci ret = argc == 0 || global_help 297e1051a39Sopenharmony_ci ? do_cmd(prog, 1, help_argv) 298e1051a39Sopenharmony_ci : do_cmd(prog, argc, argv); 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_ci end: 301e1051a39Sopenharmony_ci OPENSSL_free(default_config_file); 302e1051a39Sopenharmony_ci lh_FUNCTION_free(prog); 303e1051a39Sopenharmony_ci OPENSSL_free(arg.argv); 304e1051a39Sopenharmony_ci if (!app_RAND_write()) 305e1051a39Sopenharmony_ci ret = EXIT_FAILURE; 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci BIO_free(bio_in); 308e1051a39Sopenharmony_ci BIO_free_all(bio_out); 309e1051a39Sopenharmony_ci apps_shutdown(); 310e1051a39Sopenharmony_ci BIO_free_all(bio_err); 311e1051a39Sopenharmony_ci EXIT(ret); 312e1051a39Sopenharmony_ci} 313e1051a39Sopenharmony_ci 314e1051a39Sopenharmony_citypedef enum HELP_CHOICE { 315e1051a39Sopenharmony_ci OPT_hERR = -1, OPT_hEOF = 0, OPT_hHELP 316e1051a39Sopenharmony_ci} HELP_CHOICE; 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ciconst OPTIONS help_options[] = { 319e1051a39Sopenharmony_ci {OPT_HELP_STR, 1, '-', "Usage: help [options] [command]\n"}, 320e1051a39Sopenharmony_ci 321e1051a39Sopenharmony_ci OPT_SECTION("General"), 322e1051a39Sopenharmony_ci {"help", OPT_hHELP, '-', "Display this summary"}, 323e1051a39Sopenharmony_ci 324e1051a39Sopenharmony_ci OPT_PARAMETERS(), 325e1051a39Sopenharmony_ci {"command", 0, 0, "Name of command to display help (optional)"}, 326e1051a39Sopenharmony_ci {NULL} 327e1051a39Sopenharmony_ci}; 328e1051a39Sopenharmony_ci 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ciint help_main(int argc, char **argv) 331e1051a39Sopenharmony_ci{ 332e1051a39Sopenharmony_ci FUNCTION *fp; 333e1051a39Sopenharmony_ci int i, nl; 334e1051a39Sopenharmony_ci FUNC_TYPE tp; 335e1051a39Sopenharmony_ci char *prog; 336e1051a39Sopenharmony_ci HELP_CHOICE o; 337e1051a39Sopenharmony_ci DISPLAY_COLUMNS dc; 338e1051a39Sopenharmony_ci char *new_argv[3]; 339e1051a39Sopenharmony_ci 340e1051a39Sopenharmony_ci prog = opt_init(argc, argv, help_options); 341e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_hEOF) { 342e1051a39Sopenharmony_ci switch (o) { 343e1051a39Sopenharmony_ci case OPT_hERR: 344e1051a39Sopenharmony_ci case OPT_hEOF: 345e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 346e1051a39Sopenharmony_ci return 1; 347e1051a39Sopenharmony_ci case OPT_hHELP: 348e1051a39Sopenharmony_ci opt_help(help_options); 349e1051a39Sopenharmony_ci return 0; 350e1051a39Sopenharmony_ci } 351e1051a39Sopenharmony_ci } 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ci /* One optional argument, the command to get help for. */ 354e1051a39Sopenharmony_ci if (opt_num_rest() == 1) { 355e1051a39Sopenharmony_ci new_argv[0] = opt_rest()[0]; 356e1051a39Sopenharmony_ci new_argv[1] = "--help"; 357e1051a39Sopenharmony_ci new_argv[2] = NULL; 358e1051a39Sopenharmony_ci return do_cmd(prog_init(), 2, new_argv); 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci if (opt_num_rest() != 0) { 361e1051a39Sopenharmony_ci BIO_printf(bio_err, "Usage: %s\n", prog); 362e1051a39Sopenharmony_ci return 1; 363e1051a39Sopenharmony_ci } 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci calculate_columns(functions, &dc); 366e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s:\n\nStandard commands", prog); 367e1051a39Sopenharmony_ci i = 0; 368e1051a39Sopenharmony_ci tp = FT_none; 369e1051a39Sopenharmony_ci for (fp = functions; fp->name != NULL; fp++) { 370e1051a39Sopenharmony_ci nl = 0; 371e1051a39Sopenharmony_ci if (i++ % dc.columns == 0) { 372e1051a39Sopenharmony_ci BIO_printf(bio_err, "\n"); 373e1051a39Sopenharmony_ci nl = 1; 374e1051a39Sopenharmony_ci } 375e1051a39Sopenharmony_ci if (fp->type != tp) { 376e1051a39Sopenharmony_ci tp = fp->type; 377e1051a39Sopenharmony_ci if (!nl) 378e1051a39Sopenharmony_ci BIO_printf(bio_err, "\n"); 379e1051a39Sopenharmony_ci if (tp == FT_md) { 380e1051a39Sopenharmony_ci i = 1; 381e1051a39Sopenharmony_ci BIO_printf(bio_err, 382e1051a39Sopenharmony_ci "\nMessage Digest commands (see the `dgst' command for more details)\n"); 383e1051a39Sopenharmony_ci } else if (tp == FT_cipher) { 384e1051a39Sopenharmony_ci i = 1; 385e1051a39Sopenharmony_ci BIO_printf(bio_err, 386e1051a39Sopenharmony_ci "\nCipher commands (see the `enc' command for more details)\n"); 387e1051a39Sopenharmony_ci } 388e1051a39Sopenharmony_ci } 389e1051a39Sopenharmony_ci BIO_printf(bio_err, "%-*s", dc.width, fp->name); 390e1051a39Sopenharmony_ci } 391e1051a39Sopenharmony_ci BIO_printf(bio_err, "\n\n"); 392e1051a39Sopenharmony_ci return 0; 393e1051a39Sopenharmony_ci} 394e1051a39Sopenharmony_ci 395e1051a39Sopenharmony_cistatic int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) 396e1051a39Sopenharmony_ci{ 397e1051a39Sopenharmony_ci FUNCTION f, *fp; 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci if (argc <= 0 || argv[0] == NULL) 400e1051a39Sopenharmony_ci return 0; 401e1051a39Sopenharmony_ci memset(&f, 0, sizeof(f)); 402e1051a39Sopenharmony_ci f.name = argv[0]; 403e1051a39Sopenharmony_ci fp = lh_FUNCTION_retrieve(prog, &f); 404e1051a39Sopenharmony_ci if (fp == NULL) { 405e1051a39Sopenharmony_ci if (EVP_get_digestbyname(argv[0])) { 406e1051a39Sopenharmony_ci f.type = FT_md; 407e1051a39Sopenharmony_ci f.func = dgst_main; 408e1051a39Sopenharmony_ci fp = &f; 409e1051a39Sopenharmony_ci } else if (EVP_get_cipherbyname(argv[0])) { 410e1051a39Sopenharmony_ci f.type = FT_cipher; 411e1051a39Sopenharmony_ci f.func = enc_main; 412e1051a39Sopenharmony_ci fp = &f; 413e1051a39Sopenharmony_ci } 414e1051a39Sopenharmony_ci } 415e1051a39Sopenharmony_ci if (fp != NULL) { 416e1051a39Sopenharmony_ci if (fp->deprecated_alternative != NULL) 417e1051a39Sopenharmony_ci warn_deprecated(fp); 418e1051a39Sopenharmony_ci return fp->func(argc, argv); 419e1051a39Sopenharmony_ci } 420e1051a39Sopenharmony_ci if ((strncmp(argv[0], "no-", 3)) == 0) { 421e1051a39Sopenharmony_ci /* 422e1051a39Sopenharmony_ci * User is asking if foo is unsupported, by trying to "run" the 423e1051a39Sopenharmony_ci * no-foo command. Strange. 424e1051a39Sopenharmony_ci */ 425e1051a39Sopenharmony_ci f.name = argv[0] + 3; 426e1051a39Sopenharmony_ci if (lh_FUNCTION_retrieve(prog, &f) == NULL) { 427e1051a39Sopenharmony_ci BIO_printf(bio_out, "%s\n", argv[0]); 428e1051a39Sopenharmony_ci return 0; 429e1051a39Sopenharmony_ci } 430e1051a39Sopenharmony_ci BIO_printf(bio_out, "%s\n", argv[0] + 3); 431e1051a39Sopenharmony_ci return 1; 432e1051a39Sopenharmony_ci } 433e1051a39Sopenharmony_ci 434e1051a39Sopenharmony_ci BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", 435e1051a39Sopenharmony_ci argv[0]); 436e1051a39Sopenharmony_ci return 1; 437e1051a39Sopenharmony_ci} 438e1051a39Sopenharmony_ci 439e1051a39Sopenharmony_cistatic int function_cmp(const FUNCTION * a, const FUNCTION * b) 440e1051a39Sopenharmony_ci{ 441e1051a39Sopenharmony_ci return strncmp(a->name, b->name, 8); 442e1051a39Sopenharmony_ci} 443e1051a39Sopenharmony_ci 444e1051a39Sopenharmony_cistatic unsigned long function_hash(const FUNCTION * a) 445e1051a39Sopenharmony_ci{ 446e1051a39Sopenharmony_ci return OPENSSL_LH_strhash(a->name); 447e1051a39Sopenharmony_ci} 448e1051a39Sopenharmony_ci 449e1051a39Sopenharmony_cistatic int SortFnByName(const void *_f1, const void *_f2) 450e1051a39Sopenharmony_ci{ 451e1051a39Sopenharmony_ci const FUNCTION *f1 = _f1; 452e1051a39Sopenharmony_ci const FUNCTION *f2 = _f2; 453e1051a39Sopenharmony_ci 454e1051a39Sopenharmony_ci if (f1->type != f2->type) 455e1051a39Sopenharmony_ci return f1->type - f2->type; 456e1051a39Sopenharmony_ci return strcmp(f1->name, f2->name); 457e1051a39Sopenharmony_ci} 458e1051a39Sopenharmony_ci 459e1051a39Sopenharmony_cistatic LHASH_OF(FUNCTION) *prog_init(void) 460e1051a39Sopenharmony_ci{ 461e1051a39Sopenharmony_ci static LHASH_OF(FUNCTION) *ret = NULL; 462e1051a39Sopenharmony_ci static int prog_inited = 0; 463e1051a39Sopenharmony_ci FUNCTION *f; 464e1051a39Sopenharmony_ci size_t i; 465e1051a39Sopenharmony_ci 466e1051a39Sopenharmony_ci if (prog_inited) 467e1051a39Sopenharmony_ci return ret; 468e1051a39Sopenharmony_ci 469e1051a39Sopenharmony_ci prog_inited = 1; 470e1051a39Sopenharmony_ci 471e1051a39Sopenharmony_ci /* Sort alphabetically within category. For nicer help displays. */ 472e1051a39Sopenharmony_ci for (i = 0, f = functions; f->name != NULL; ++f, ++i) 473e1051a39Sopenharmony_ci ; 474e1051a39Sopenharmony_ci qsort(functions, i, sizeof(*functions), SortFnByName); 475e1051a39Sopenharmony_ci 476e1051a39Sopenharmony_ci if ((ret = lh_FUNCTION_new(function_hash, function_cmp)) == NULL) 477e1051a39Sopenharmony_ci return NULL; 478e1051a39Sopenharmony_ci 479e1051a39Sopenharmony_ci for (f = functions; f->name != NULL; f++) 480e1051a39Sopenharmony_ci (void)lh_FUNCTION_insert(ret, f); 481e1051a39Sopenharmony_ci return ret; 482e1051a39Sopenharmony_ci} 483