X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fengine.c;h=b60bfbc29416a536c5456f697a4638ef46e7879a;hp=f71076b13b0f203af2d868d117e0770c4bebceec;hb=1da12e34ed69cec206f3a251a1e62ceeb694a6ea;hpb=817dfc18a31cc1b1281f5e7396abf2064f0c2a10 diff --git a/apps/engine.c b/apps/engine.c index f71076b13b..b60bfbc294 100644 --- a/apps/engine.c +++ b/apps/engine.c @@ -1,6 +1,6 @@ -/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ -/* Written by Richard Levitte for the OpenSSL - * project 2000. +/* + * Written by Richard Levitte for the OpenSSL project + * 2000. */ /* ==================================================================== * Copyright (c) 2000 The OpenSSL Project. All rights reserved. @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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 @@ -56,462 +56,435 @@ * */ -#include -#include -#include -#ifdef OPENSSL_NO_STDIO -#define APPS_WIN16 -#endif -#include "apps.h" -#include -#include -#include - -#undef PROG -#define PROG engine_main +#include +#ifdef OPENSSL_NO_ENGINE +NON_EMPTY_TRANSLATION_UNIT +#else -static 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 - for each engine, check that they are really available\n", -" -pre - runs command 'cmd' against the ENGINE before any attempts\n", -" to load it (if -t is used)\n", -" -post - 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 -}; +# include "apps.h" +# include +# include +# include +# include +# include +# include -static void identity(void *ptr) - { - return; - } +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 int append_buf(char **buf, const char *s, int *size, int step) - { - int l = strlen(s); +OPTIONS engine_options[] = { + {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, + {OPT_HELP_STR, 1, '-', + " engine... Engines to load\n"}, + {"help", OPT_HELP, '-', "Display this summary"}, + {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, + {"vv", OPT_VV, '-', "Also display each command's description"}, + {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, + {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, + {"c", OPT_C, '-', "List the capabilities of specified engine"}, + {"t", OPT_T, '-', "Check that specified 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} +}; - if (*buf == NULL) - { - *size = step; - *buf = OPENSSL_malloc(*size); - if (*buf == NULL) - return 0; - **buf = '\0'; - } +static void identity(char *ptr) +{ +} - if (**buf != '\0') - l += 2; /* ", " */ +static int append_buf(char **buf, int *size, const char *s) +{ + if (*buf == NULL) { + *size = 256; + *buf = app_malloc(*size, "engine buffer"); + **buf = '\0'; + } - if (strlen(*buf) + strlen(s) >= (unsigned int)*size) - { - *size += step; - *buf = OPENSSL_realloc(*buf, *size); - } + if (strlen(*buf) + strlen(s) >= (unsigned int)*size) { + *size += 256; + *buf = OPENSSL_realloc(*buf, *size); + } - if (*buf == NULL) - return 0; + if (*buf == NULL) + return 0; - if (**buf != '\0') - strcat(*buf, ", "); - strcat(*buf, s); + if (**buf != '\0') + OPENSSL_strlcat(*buf, ", ", *size); + OPENSSL_strlcat(*buf, s, *size); - return 1; - } + return 1; +} -static int util_flags(BIO *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); - if(flags == 0) - { - BIO_printf(bio_out, "\n"); - return 1; - } - /* If the object is internal, mark it in a way that shows instead of - * having it part of all the other flags, even if it really is. */ - if(flags & ENGINE_CMD_FLAG_INTERNAL) - { - BIO_printf(bio_out, "[Internal] "); - } +static int util_flags(BIO *out, unsigned int flags, const char *indent) +{ + int started = 0, err = 0; + /* Indent before displaying input flags */ + BIO_printf(out, "%s%s(input flags): ", indent, indent); + if (flags == 0) { + BIO_printf(out, "\n"); + return 1; + } + /* + * If the object is internal, mark it in a way that shows instead of + * having it part of all the other flags, even if it really is. + */ + if (flags & ENGINE_CMD_FLAG_INTERNAL) { + BIO_printf(out, "[Internal] "); + } - if(flags & ENGINE_CMD_FLAG_NUMERIC) - { - if(started) - { - BIO_printf(bio_out, "|"); - err = 1; - } - BIO_printf(bio_out, "NUMERIC"); - started = 1; - } - /* Now we check that no combinations of the mutually exclusive NUMERIC, - * STRING, and NO_INPUT flags have been used. Future flags that can be - * OR'd together with these would need to added after these to preserve - * the testing logic. */ - if(flags & ENGINE_CMD_FLAG_STRING) - { - if(started) - { - BIO_printf(bio_out, "|"); - err = 1; - } - BIO_printf(bio_out, "STRING"); - started = 1; - } - if(flags & ENGINE_CMD_FLAG_NO_INPUT) - { - if(started) - { - BIO_printf(bio_out, "|"); - err = 1; - } - BIO_printf(bio_out, "NO_INPUT"); - started = 1; - } - /* Check for unknown flags */ - flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & - ~ENGINE_CMD_FLAG_STRING & - ~ENGINE_CMD_FLAG_NO_INPUT & - ~ENGINE_CMD_FLAG_INTERNAL; - if(flags) - { - if(started) BIO_printf(bio_out, "|"); - BIO_printf(bio_out, "<0x%04X>", flags); - } - if(err) - BIO_printf(bio_out, " "); - BIO_printf(bio_out, "\n"); - return 1; - } + if (flags & ENGINE_CMD_FLAG_NUMERIC) { + BIO_printf(out, "NUMERIC"); + started = 1; + } + /* + * Now we check that no combinations of the mutually exclusive NUMERIC, + * STRING, and NO_INPUT flags have been used. Future flags that can be + * OR'd together with these would need to added after these to preserve + * the testing logic. + */ + if (flags & ENGINE_CMD_FLAG_STRING) { + if (started) { + BIO_printf(out, "|"); + err = 1; + } + BIO_printf(out, "STRING"); + started = 1; + } + if (flags & ENGINE_CMD_FLAG_NO_INPUT) { + if (started) { + BIO_printf(out, "|"); + err = 1; + } + BIO_printf(out, "NO_INPUT"); + started = 1; + } + /* Check for unknown flags */ + flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & + ~ENGINE_CMD_FLAG_STRING & + ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; + if (flags) { + if (started) + BIO_printf(out, "|"); + BIO_printf(out, "<0x%04X>", flags); + } + if (err) + BIO_printf(out, " "); + BIO_printf(out, "\n"); + return 1; +} -static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent) - { - static const int line_wrap = 78; - int num; - int ret = 0; - char *name = NULL; - char *desc = NULL; - int flags; - int xpos = 0; - STACK *cmds = NULL; - if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || - ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, - 0, NULL, NULL)) <= 0)) - { -#if 0 - BIO_printf(bio_out, "%s\n", indent); -#endif - return 1; - } +static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent) +{ + static const int line_wrap = 78; + int num; + int ret = 0; + char *name = NULL; + char *desc = NULL; + int flags; + int xpos = 0; + STACK_OF(OPENSSL_STRING) *cmds = NULL; + if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || + ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, + 0, NULL, NULL)) <= 0)) { + return 1; + } - cmds = sk_new_null(); + cmds = sk_OPENSSL_STRING_new_null(); + if (!cmds) + goto err; - if(!cmds) - goto err; - do { - int len; - /* Get the command input flags */ - if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, - NULL, NULL)) < 0) - goto err; - if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) - { - /* Get the command name */ - if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, - NULL, NULL)) <= 0) - goto err; - if((name = OPENSSL_malloc(len + 1)) == NULL) - goto err; - if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, + do { + int len; + /* Get the command input flags */ + if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, + NULL, NULL)) < 0) + goto err; + if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { + /* Get the command name */ + if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, + NULL, NULL)) <= 0) + goto err; + name = app_malloc(len + 1, "name buffer"); + if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, + NULL) <= 0) + goto err; + /* Get the command description */ + if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, + NULL, NULL)) < 0) + goto err; + if (len > 0) { + desc = app_malloc(len + 1, "description buffer"); + if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, NULL) <= 0) - goto err; - /* Get the command description */ - if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, - NULL, NULL)) < 0) - goto err; - if(len > 0) - { - if((desc = OPENSSL_malloc(len + 1)) == NULL) - goto err; - if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, - NULL) <= 0) - goto err; - } - /* Now decide on the output */ - if(xpos == 0) - /* Do an indent */ - xpos = BIO_printf(bio_out, indent); - else - /* Otherwise prepend a ", " */ - xpos += BIO_printf(bio_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_printf(bio_out, indent); - } - xpos += BIO_printf(bio_out, "%s", name); - } - else - { - /* We're listing names plus descriptions */ - BIO_printf(bio_out, "%s: %s\n", name, - (desc == NULL) ? "" : desc); - /* ... and sometimes input flags */ - if((verbose >= 3) && !util_flags(bio_out, flags, - indent)) - goto err; - xpos = 0; - } - } - OPENSSL_free(name); name = NULL; - if(desc) { OPENSSL_free(desc); desc = NULL; } - /* Move to the next command */ - num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, - num, NULL, NULL); - } while(num > 0); - if(xpos > 0) - BIO_printf(bio_out, "\n"); - ret = 1; -err: - if(cmds) sk_pop_free(cmds, identity); - if(name) OPENSSL_free(name); - if(desc) OPENSSL_free(desc); - return ret; - } + goto err; + } + /* Now decide on the output */ + if (xpos == 0) + /* Do an indent */ + xpos = BIO_puts(out, indent); + else + /* Otherwise prepend a ", " */ + 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(out, "\n"); + xpos = BIO_puts(out, indent); + } + xpos += BIO_printf(out, "%s", name); + } else { + /* We're listing names plus descriptions */ + BIO_printf(out, "%s: %s\n", name, + (desc == NULL) ? "" : desc); + /* ... and sometimes input flags */ + if ((verbose >= 3) && !util_flags(out, flags, indent)) + goto err; + xpos = 0; + } + } + OPENSSL_free(name); + name = NULL; + OPENSSL_free(desc); + desc = NULL; + /* Move to the next command */ + num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); + } while (num > 0); + if (xpos > 0) + BIO_printf(out, "\n"); + ret = 1; + err: + sk_OPENSSL_STRING_pop_free(cmds, identity); + OPENSSL_free(name); + OPENSSL_free(desc); + return ret; +} -static void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent) - { - int loop, res, num = sk_num(cmds); - if(num < 0) - { - BIO_printf(bio_out, "[Error]: internal stack error\n"); - return; - } - for(loop = 0; loop < num; loop++) - { - char buf[256]; - const char *cmd, *arg; - cmd = sk_value(cmds, loop); - res = 1; /* assume success */ - /* Check if this command has no ":arg" */ - if((arg = strstr(cmd, ":")) == NULL) - { - if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) - res = 0; - } - else - { - if((int)(arg - cmd) > 254) - { - BIO_printf(bio_out,"[Error]: command name too long\n"); - return; - } - memcpy(buf, cmd, (int)(arg - cmd)); - buf[arg-cmd] = '\0'; - arg++; /* Move past the ":" */ - /* Call the command with the argument */ - if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) - res = 0; - } - if(res) - BIO_printf(bio_out, "[Success]: %s\n", cmd); - else - { - BIO_printf(bio_out, "[Failure]: %s\n", cmd); - ERR_print_errors(bio_out); - } - } - } +static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, + BIO *out, const char *indent) +{ + int loop, res, num = sk_OPENSSL_STRING_num(cmds); -int MAIN(int, char **); + if (num < 0) { + BIO_printf(out, "[Error]: internal stack error\n"); + return; + } + for (loop = 0; loop < num; loop++) { + char buf[256]; + const char *cmd, *arg; + cmd = sk_OPENSSL_STRING_value(cmds, loop); + res = 1; /* assume success */ + /* Check if this command has no ":arg" */ + if ((arg = strstr(cmd, ":")) == NULL) { + if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) + res = 0; + } else { + if ((int)(arg - cmd) > 254) { + BIO_printf(out, "[Error]: command name too long\n"); + return; + } + memcpy(buf, cmd, (int)(arg - cmd)); + buf[arg - cmd] = '\0'; + arg++; /* Move past the ":" */ + /* Call the command with the argument */ + if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) + res = 0; + } + if (res) + BIO_printf(out, "[Success]: %s\n", cmd); + else { + BIO_printf(out, "[Failure]: %s\n", cmd); + ERR_print_errors(out); + } + } +} -int MAIN(int argc, char **argv) - { - int ret=1,i; - char **pp; - int verbose=0, list_cap=0, test_avail=0; - ENGINE *e; - STACK *engines = sk_new_null(); - STACK *pre_cmds = sk_new_null(); - STACK *post_cmds = sk_new_null(); - int badops=1; - BIO *bio_out=NULL; - const char *indent = " "; +int engine_main(int argc, char **argv) +{ + int ret = 1, i; + 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(); + BIO *out; + const char *indent = " "; + OPTION_CHOICE o; + char *prog; + char *argv1; - apps_startup(); - SSL_load_error_strings(); + out = dup_bio_out(FORMAT_TEXT); + if (engines == NULL || pre_cmds == NULL || post_cmds == NULL) + goto end; - if (bio_err == NULL) - bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); - 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 + /* Remember the original command name, parse/skip any leading engine + * names, and then setup to parse the rest of the line as flags. */ + prog = argv[0]; + while ((argv1 = argv[1]) != NULL && *argv1 != '-') { + sk_OPENSSL_STRING_push(engines, argv1); + argc--; + argv++; + } + argv[0] = prog; + opt_init(argc, argv, engine_options); - 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) - list_cap=1; - else if (strcmp(*argv,"-t") == 0) - test_avail=1; - else if (strcmp(*argv,"-pre") == 0) - { - argc--; argv++; - sk_push(pre_cmds,*argv); - } - else if (strcmp(*argv,"-post") == 0) - { - argc--; argv++; - sk_push(post_cmds,*argv); - } - else if ((strncmp(*argv,"-h",2) == 0) || - (strcmp(*argv,"-?") == 0)) - goto skip_arg_loop; - else - sk_push(engines,*argv); - argc--; - argv++; - } - /* Looks like everything went OK */ - badops = 0; -skip_arg_loop: + 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; + 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; + } + } - if (badops) - { - for (pp=engine_usage; (*pp != NULL); pp++) - BIO_printf(bio_err,"%s",*pp); - goto end; - } + /* Allow any trailing parameters as engine names. */ + argc = opt_num_rest(); + argv = opt_rest(); + for ( ; *argv; argv++) { + if (**argv == '-') { + BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n", + prog); + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + } + sk_OPENSSL_STRING_push(engines, *argv); + } - if (sk_num(engines) == 0) - { - for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) - { - sk_push(engines,(char *)ENGINE_get_id(e)); - } - } + if (sk_OPENSSL_STRING_num(engines) == 0) { + for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { + sk_OPENSSL_STRING_push(engines, (char *)ENGINE_get_id(e)); + } + } - for (i=0; i 0) && !util_verbose(e, verbose, bio_out, indent)) - goto end; - ENGINE_free(e); - } - else - ERR_print_errors(bio_err); - } + OPENSSL_free(cap_buf); + } + if (test_avail) { + BIO_printf(out, "%s", indent); + if (ENGINE_init(e)) { + BIO_printf(out, "[ available ]\n"); + util_do_cmds(e, post_cmds, out, indent); + ENGINE_finish(e); + } else { + BIO_printf(out, "[ unavailable ]\n"); + if (test_avail_noise) + ERR_print_errors_fp(stdout); + ERR_clear_error(); + } + } + if ((verbose > 0) && !util_verbose(e, verbose, out, indent)) + goto end; + ENGINE_free(e); + } else + ERR_print_errors(bio_err); + } - ret=0; -end: - ERR_print_errors(bio_err); - sk_pop_free(engines, identity); - sk_pop_free(pre_cmds, identity); - sk_pop_free(post_cmds, identity); - if (bio_out != NULL) BIO_free_all(bio_out); - apps_shutdown(); - EXIT(ret); - } + ret = 0; + end: + + ERR_print_errors(bio_err); + 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(out); + return (ret); +} +#endif