Big apps cleanup (option-parsing, etc)

This is merges the old "rsalz-monolith" branch over to master.  The biggest
change is that option parsing switch from cascasding 'else if strcmp("-foo")'
to a utility routine and somethin akin to getopt.  Also, an error in the
command line no longer prints the full summary; use -help (or --help :)
for that.  There have been many other changes and code-cleanup, see
bullet list below.

Special thanks to Matt for the long and detailed code review.

TEMPORARY:
        For now, comment out CRYPTO_mem_leaks() at end of main

Tickets closed:
        RT3515: Use 3DES in pkcs12 if built with no-rc2
        RT1766: s_client -reconnect and -starttls broke
        RT2932: Catch write errors
        RT2604: port should be 'unsigned short'
        RT2983: total_bytes undeclared #ifdef RENEG
        RT1523: Add -nocert to fix output in x509 app
        RT3508: Remove unused variable introduced by b09eb24
        RT3511: doc fix; req default serial is random
        RT1325,2973: Add more extensions to c_rehash
        RT2119,3407: Updated to dgst.pod
        RT2379: Additional typo fix
        RT2693: Extra include of string.h
        RT2880: HFS is case-insensitive filenames
        RT3246: req command prints version number wrong

Other changes; incompatibilities marked with *:
        Add SCSV support
        Add -misalign to speed command
        Make dhparam, dsaparam, ecparam, x509 output C in proper style
        Make some internal ocsp.c functions void
        Only display cert usages with -help in verify
        Use global bio_err, remove "BIO*err" parameter from functions
        For filenames, - always means stdin (or stdout as appropriate)
        Add aliases for -des/aes "wrap" ciphers.
        *Remove support for IISSGC (server gated crypto)
        *The undocumented OCSP -header flag is now "-header name=value"
        *Documented the OCSP -header flag

Reviewed-by: Matt Caswell <matt@openssl.org>
This commit is contained in:
Rich Salz
2015-04-24 15:26:15 -04:00
parent 53dd4ddf71
commit 7e1b748570
65 changed files with 10893 additions and 13269 deletions

View File

@@ -1,4 +1,3 @@
/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */
/*
* Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
* 2000.
@@ -66,27 +65,26 @@
# include <openssl/engine.h>
# include <openssl/ssl.h>
# undef PROG
# define PROG engine_main
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
} OPTION_CHOICE;
static const char *engine_usage[] = {
"usage: engine opts [engine ...]\n",
" -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n",
" -vv will additionally display each command's description\n",
" -vvv will also add the input flags for each command\n",
" -vvvv will also show internal input flags\n",
" -c - for each engine, also list the capabilities\n",
" -t[t] - for each engine, check that they are really available\n",
" -tt will display error trace for unavailable engines\n",
" -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n",
" to load it (if -t is used)\n",
" -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n",
" (only used if -t is also provided)\n",
" NB: -pre and -post will be applied to all ENGINEs supplied on the command\n",
" line, or all supported ENGINEs if none are specified.\n",
" Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n",
" argument \"/lib/libdriver.so\".\n",
NULL
OPTIONS engine_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
{"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
{"vv", OPT_VV, '-', "Also display each command's description"},
{"v", OPT_V, '-', "For each engine, list its 'control commands'"},
{"c", OPT_C, '-', "List the capabilities of each engine"},
{"t", OPT_T, '-', "Check that each engine is available"},
{"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
{"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
{"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
{OPT_MORE_STR, OPT_EOF, 1,
"Commands are like \"SO_PATH:/lib/libdriver.so\""},
{NULL}
};
static void identity(char *ptr)
@@ -124,13 +122,13 @@ static int append_buf(char **buf, const char *s, int *size, int step)
return 1;
}
static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
static int util_flags(BIO *out, unsigned int flags, const char *indent)
{
int started = 0, err = 0;
/* Indent before displaying input flags */
BIO_printf(bio_out, "%s%s(input flags): ", indent, indent);
BIO_printf(out, "%s%s(input flags): ", indent, indent);
if (flags == 0) {
BIO_printf(bio_out, "<no flags>\n");
BIO_printf(out, "<no flags>\n");
return 1;
}
/*
@@ -138,11 +136,11 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
* having it part of all the other flags, even if it really is.
*/
if (flags & ENGINE_CMD_FLAG_INTERNAL) {
BIO_printf(bio_out, "[Internal] ");
BIO_printf(out, "[Internal] ");
}
if (flags & ENGINE_CMD_FLAG_NUMERIC) {
BIO_printf(bio_out, "NUMERIC");
BIO_printf(out, "NUMERIC");
started = 1;
}
/*
@@ -153,18 +151,18 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
*/
if (flags & ENGINE_CMD_FLAG_STRING) {
if (started) {
BIO_printf(bio_out, "|");
BIO_printf(out, "|");
err = 1;
}
BIO_printf(bio_out, "STRING");
BIO_printf(out, "STRING");
started = 1;
}
if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
if (started) {
BIO_printf(bio_out, "|");
BIO_printf(out, "|");
err = 1;
}
BIO_printf(bio_out, "NO_INPUT");
BIO_printf(out, "NO_INPUT");
started = 1;
}
/* Check for unknown flags */
@@ -173,17 +171,16 @@ static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL;
if (flags) {
if (started)
BIO_printf(bio_out, "|");
BIO_printf(bio_out, "<0x%04X>", flags);
BIO_printf(out, "|");
BIO_printf(out, "<0x%04X>", flags);
}
if (err)
BIO_printf(bio_out, " <illegal flags!>");
BIO_printf(bio_out, "\n");
BIO_printf(out, " <illegal flags!>");
BIO_printf(out, "\n");
return 1;
}
static int util_verbose(ENGINE *e, int verbose, BIO *bio_out,
const char *indent)
static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent)
{
static const int line_wrap = 78;
int num;
@@ -200,9 +197,9 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out,
}
cmds = sk_OPENSSL_STRING_new_null();
if (!cmds)
goto err;
do {
int len;
/* Get the command input flags */
@@ -233,26 +230,26 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out,
/* Now decide on the output */
if (xpos == 0)
/* Do an indent */
xpos = BIO_puts(bio_out, indent);
xpos = BIO_puts(out, indent);
else
/* Otherwise prepend a ", " */
xpos += BIO_printf(bio_out, ", ");
xpos += BIO_printf(out, ", ");
if (verbose == 1) {
/*
* We're just listing names, comma-delimited
*/
if ((xpos > (int)strlen(indent)) &&
(xpos + (int)strlen(name) > line_wrap)) {
BIO_printf(bio_out, "\n");
xpos = BIO_puts(bio_out, indent);
BIO_printf(out, "\n");
xpos = BIO_puts(out, indent);
}
xpos += BIO_printf(bio_out, "%s", name);
xpos += BIO_printf(out, "%s", name);
} else {
/* We're listing names plus descriptions */
BIO_printf(bio_out, "%s: %s\n", name,
BIO_printf(out, "%s: %s\n", name,
(desc == NULL) ? "<no description>" : desc);
/* ... and sometimes input flags */
if ((verbose >= 3) && !util_flags(bio_out, flags, indent))
if ((verbose >= 3) && !util_flags(out, flags, indent))
goto err;
xpos = 0;
}
@@ -267,7 +264,7 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out,
num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL);
} while (num > 0);
if (xpos > 0)
BIO_printf(bio_out, "\n");
BIO_printf(out, "\n");
ret = 1;
err:
if (cmds)
@@ -280,12 +277,12 @@ static int util_verbose(ENGINE *e, int verbose, BIO *bio_out,
}
static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
BIO *bio_out, const char *indent)
BIO *out, const char *indent)
{
int loop, res, num = sk_OPENSSL_STRING_num(cmds);
if (num < 0) {
BIO_printf(bio_out, "[Error]: internal stack error\n");
BIO_printf(out, "[Error]: internal stack error\n");
return;
}
for (loop = 0; loop < num; loop++) {
@@ -299,7 +296,7 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
res = 0;
} else {
if ((int)(arg - cmd) > 254) {
BIO_printf(bio_out, "[Error]: command name too long\n");
BIO_printf(out, "[Error]: command name too long\n");
return;
}
memcpy(buf, cmd, (int)(arg - cmd));
@@ -310,90 +307,70 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
res = 0;
}
if (res)
BIO_printf(bio_out, "[Success]: %s\n", cmd);
BIO_printf(out, "[Success]: %s\n", cmd);
else {
BIO_printf(bio_out, "[Failure]: %s\n", cmd);
ERR_print_errors(bio_out);
BIO_printf(out, "[Failure]: %s\n", cmd);
ERR_print_errors(out);
}
}
}
int MAIN(int, char **);
int MAIN(int argc, char **argv)
int engine_main(int argc, char **argv)
{
int ret = 1, i;
const char **pp;
int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
ENGINE *e;
STACK_OF(OPENSSL_STRING) *engines = sk_OPENSSL_STRING_new_null();
STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null();
STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null();
int badops = 1;
BIO *bio_out = NULL;
BIO *out;
const char *indent = " ";
OPTION_CHOICE o;
char *prog;
apps_startup();
SSL_load_error_strings();
if (bio_err == NULL)
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
if (!load_config(bio_err, NULL))
out = dup_bio_out();
prog = opt_init(argc, argv, engine_options);
if (!engines || !pre_cmds || !post_cmds)
goto end;
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
# ifdef OPENSSL_SYS_VMS
{
BIO *tmpbio = BIO_new(BIO_f_linebuffer());
bio_out = BIO_push(tmpbio, bio_out);
}
# endif
argc--;
argv++;
while (argc >= 1) {
if (strncmp(*argv, "-v", 2) == 0) {
if (strspn(*argv + 1, "v") < strlen(*argv + 1))
goto skip_arg_loop;
if ((verbose = strlen(*argv + 1)) > 4)
goto skip_arg_loop;
} else if (strcmp(*argv, "-c") == 0)
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(engine_options);
ret = 0;
goto end;
case OPT_VVVV:
case OPT_VVV:
case OPT_VV:
case OPT_V:
/* Convert to an integer from one to four. */
i = (int)(o - OPT_V) + 1;
if (verbose < i)
verbose = i;
break;
case OPT_C:
list_cap = 1;
else if (strncmp(*argv, "-t", 2) == 0) {
test_avail = 1;
if (strspn(*argv + 1, "t") < strlen(*argv + 1))
goto skip_arg_loop;
if ((test_avail_noise = strlen(*argv + 1) - 1) > 1)
goto skip_arg_loop;
} else if (strcmp(*argv, "-pre") == 0) {
argc--;
argv++;
if (argc == 0)
goto skip_arg_loop;
sk_OPENSSL_STRING_push(pre_cmds, *argv);
} else if (strcmp(*argv, "-post") == 0) {
argc--;
argv++;
if (argc == 0)
goto skip_arg_loop;
sk_OPENSSL_STRING_push(post_cmds, *argv);
} else if ((strncmp(*argv, "-h", 2) == 0) ||
(strcmp(*argv, "-?") == 0))
goto skip_arg_loop;
else
sk_OPENSSL_STRING_push(engines, *argv);
argc--;
argv++;
}
/* Looks like everything went OK */
badops = 0;
skip_arg_loop:
if (badops) {
for (pp = engine_usage; (*pp != NULL); pp++)
BIO_printf(bio_err, "%s", *pp);
goto end;
break;
case OPT_TT:
test_avail_noise++;
case OPT_T:
test_avail++;
break;
case OPT_PRE:
sk_OPENSSL_STRING_push(pre_cmds, opt_arg());
break;
case OPT_POST:
sk_OPENSSL_STRING_push(post_cmds, opt_arg());
break;
}
}
argc = opt_num_rest();
argv = opt_rest();
for ( ; *argv; argv++)
sk_OPENSSL_STRING_push(engines, *argv);
if (sk_OPENSSL_STRING_num(engines) == 0) {
for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
@@ -408,10 +385,10 @@ int MAIN(int argc, char **argv)
/*
* Do "id" first, then "name". Easier to auto-parse.
*/
BIO_printf(bio_out, "(%s) %s\n", id, name);
util_do_cmds(e, pre_cmds, bio_out, indent);
BIO_printf(out, "(%s) %s\n", id, name);
util_do_cmds(e, pre_cmds, out, indent);
if (strcmp(ENGINE_get_id(e), id) != 0) {
BIO_printf(bio_out, "Loaded: (%s) %s\n",
BIO_printf(out, "Loaded: (%s) %s\n",
ENGINE_get_id(e), ENGINE_get_name(e));
}
if (list_cap) {
@@ -466,24 +443,24 @@ int MAIN(int argc, char **argv)
goto end;
skip_pmeths:
if (cap_buf && (*cap_buf != '\0'))
BIO_printf(bio_out, " [%s]\n", cap_buf);
BIO_printf(out, " [%s]\n", cap_buf);
OPENSSL_free(cap_buf);
}
if (test_avail) {
BIO_printf(bio_out, "%s", indent);
BIO_printf(out, "%s", indent);
if (ENGINE_init(e)) {
BIO_printf(bio_out, "[ available ]\n");
util_do_cmds(e, post_cmds, bio_out, indent);
BIO_printf(out, "[ available ]\n");
util_do_cmds(e, post_cmds, out, indent);
ENGINE_finish(e);
} else {
BIO_printf(bio_out, "[ unavailable ]\n");
BIO_printf(out, "[ unavailable ]\n");
if (test_avail_noise)
ERR_print_errors_fp(stdout);
ERR_clear_error();
}
}
if ((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
if ((verbose > 0) && !util_verbose(e, verbose, out, indent))
goto end;
ENGINE_free(e);
} else
@@ -497,9 +474,8 @@ int MAIN(int argc, char **argv)
sk_OPENSSL_STRING_pop_free(engines, identity);
sk_OPENSSL_STRING_pop_free(pre_cmds, identity);
sk_OPENSSL_STRING_pop_free(post_cmds, identity);
BIO_free_all(bio_out);
apps_shutdown();
OPENSSL_EXIT(ret);
BIO_free_all(out);
return (ret);
}
#else