1 /* 2 * Copyright 2000-2016 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 <openssl/opensslconf.h> 11 #ifdef OPENSSL_NO_ENGINE 12 NON_EMPTY_TRANSLATION_UNIT 13 #else 14 15 # include "apps.h" 16 # include <stdio.h> 17 # include <stdlib.h> 18 # include <string.h> 19 # include <openssl/err.h> 20 # include <openssl/engine.h> 21 # include <openssl/ssl.h> 22 23 typedef enum OPTION_choice { 24 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 25 OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST, 26 OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV 27 } OPTION_CHOICE; 28 29 OPTIONS engine_options[] = { 30 {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"}, 31 {OPT_HELP_STR, 1, '-', 32 " engine... Engines to load\n"}, 33 {"help", OPT_HELP, '-', "Display this summary"}, 34 {"v", OPT_V, '-', "List 'control commands' For each specified engine"}, 35 {"vv", OPT_VV, '-', "Also display each command's description"}, 36 {"vvv", OPT_VVV, '-', "Also add the input flags for each command"}, 37 {"vvvv", OPT_VVVV, '-', "Also show internal input flags"}, 38 {"c", OPT_C, '-', "List the capabilities of specified engine"}, 39 {"t", OPT_T, '-', "Check that specified engine is available"}, 40 {"tt", OPT_TT, '-', "Display error trace for unavailable engines"}, 41 {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"}, 42 {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"}, 43 {OPT_MORE_STR, OPT_EOF, 1, 44 "Commands are like \"SO_PATH:/lib/libdriver.so\""}, 45 {NULL} 46 }; 47 48 static int append_buf(char **buf, int *size, const char *s) 49 { 50 if (*buf == NULL) { 51 *size = 256; 52 *buf = app_malloc(*size, "engine buffer"); 53 **buf = '\0'; 54 } 55 56 if (strlen(*buf) + strlen(s) >= (unsigned int)*size) { 57 char *tmp; 58 *size += 256; 59 tmp = OPENSSL_realloc(*buf, *size); 60 if (tmp == NULL) { 61 OPENSSL_free(*buf); 62 *buf = NULL; 63 return 0; 64 } 65 *buf = tmp; 66 } 67 68 if (**buf != '\0') 69 OPENSSL_strlcat(*buf, ", ", *size); 70 OPENSSL_strlcat(*buf, s, *size); 71 72 return 1; 73 } 74 75 static int util_flags(BIO *out, unsigned int flags, const char *indent) 76 { 77 int started = 0, err = 0; 78 /* Indent before displaying input flags */ 79 BIO_printf(out, "%s%s(input flags): ", indent, indent); 80 if (flags == 0) { 81 BIO_printf(out, "<no flags>\n"); 82 return 1; 83 } 84 /* 85 * If the object is internal, mark it in a way that shows instead of 86 * having it part of all the other flags, even if it really is. 87 */ 88 if (flags & ENGINE_CMD_FLAG_INTERNAL) { 89 BIO_printf(out, "[Internal] "); 90 } 91 92 if (flags & ENGINE_CMD_FLAG_NUMERIC) { 93 BIO_printf(out, "NUMERIC"); 94 started = 1; 95 } 96 /* 97 * Now we check that no combinations of the mutually exclusive NUMERIC, 98 * STRING, and NO_INPUT flags have been used. Future flags that can be 99 * OR'd together with these would need to added after these to preserve 100 * the testing logic. 101 */ 102 if (flags & ENGINE_CMD_FLAG_STRING) { 103 if (started) { 104 BIO_printf(out, "|"); 105 err = 1; 106 } 107 BIO_printf(out, "STRING"); 108 started = 1; 109 } 110 if (flags & ENGINE_CMD_FLAG_NO_INPUT) { 111 if (started) { 112 BIO_printf(out, "|"); 113 err = 1; 114 } 115 BIO_printf(out, "NO_INPUT"); 116 started = 1; 117 } 118 /* Check for unknown flags */ 119 flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & 120 ~ENGINE_CMD_FLAG_STRING & 121 ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; 122 if (flags) { 123 if (started) 124 BIO_printf(out, "|"); 125 BIO_printf(out, "<0x%04X>", flags); 126 } 127 if (err) 128 BIO_printf(out, " <illegal flags!>"); 129 BIO_printf(out, "\n"); 130 return 1; 131 } 132 133 static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent) 134 { 135 static const int line_wrap = 78; 136 int num; 137 int ret = 0; 138 char *name = NULL; 139 char *desc = NULL; 140 int flags; 141 int xpos = 0; 142 STACK_OF(OPENSSL_STRING) *cmds = NULL; 143 if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || 144 ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 145 0, NULL, NULL)) <= 0)) { 146 return 1; 147 } 148 149 cmds = sk_OPENSSL_STRING_new_null(); 150 if (!cmds) 151 goto err; 152 153 do { 154 int len; 155 /* Get the command input flags */ 156 if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, 157 NULL, NULL)) < 0) 158 goto err; 159 if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { 160 /* Get the command name */ 161 if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, 162 NULL, NULL)) <= 0) 163 goto err; 164 name = app_malloc(len + 1, "name buffer"); 165 if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, 166 NULL) <= 0) 167 goto err; 168 /* Get the command description */ 169 if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, 170 NULL, NULL)) < 0) 171 goto err; 172 if (len > 0) { 173 desc = app_malloc(len + 1, "description buffer"); 174 if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, 175 NULL) <= 0) 176 goto err; 177 } 178 /* Now decide on the output */ 179 if (xpos == 0) 180 /* Do an indent */ 181 xpos = BIO_puts(out, indent); 182 else 183 /* Otherwise prepend a ", " */ 184 xpos += BIO_printf(out, ", "); 185 if (verbose == 1) { 186 /* 187 * We're just listing names, comma-delimited 188 */ 189 if ((xpos > (int)strlen(indent)) && 190 (xpos + (int)strlen(name) > line_wrap)) { 191 BIO_printf(out, "\n"); 192 xpos = BIO_puts(out, indent); 193 } 194 xpos += BIO_printf(out, "%s", name); 195 } else { 196 /* We're listing names plus descriptions */ 197 BIO_printf(out, "%s: %s\n", name, 198 (desc == NULL) ? "<no description>" : desc); 199 /* ... and sometimes input flags */ 200 if ((verbose >= 3) && !util_flags(out, flags, indent)) 201 goto err; 202 xpos = 0; 203 } 204 } 205 OPENSSL_free(name); 206 name = NULL; 207 OPENSSL_free(desc); 208 desc = NULL; 209 /* Move to the next command */ 210 num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); 211 } while (num > 0); 212 if (xpos > 0) 213 BIO_printf(out, "\n"); 214 ret = 1; 215 err: 216 sk_OPENSSL_STRING_free(cmds); 217 OPENSSL_free(name); 218 OPENSSL_free(desc); 219 return ret; 220 } 221 222 static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, 223 BIO *out, const char *indent) 224 { 225 int loop, res, num = sk_OPENSSL_STRING_num(cmds); 226 227 if (num < 0) { 228 BIO_printf(out, "[Error]: internal stack error\n"); 229 return; 230 } 231 for (loop = 0; loop < num; loop++) { 232 char buf[256]; 233 const char *cmd, *arg; 234 cmd = sk_OPENSSL_STRING_value(cmds, loop); 235 res = 1; /* assume success */ 236 /* Check if this command has no ":arg" */ 237 if ((arg = strstr(cmd, ":")) == NULL) { 238 if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) 239 res = 0; 240 } else { 241 if ((int)(arg - cmd) > 254) { 242 BIO_printf(out, "[Error]: command name too long\n"); 243 return; 244 } 245 memcpy(buf, cmd, (int)(arg - cmd)); 246 buf[arg - cmd] = '\0'; 247 arg++; /* Move past the ":" */ 248 /* Call the command with the argument */ 249 if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) 250 res = 0; 251 } 252 if (res) 253 BIO_printf(out, "[Success]: %s\n", cmd); 254 else { 255 BIO_printf(out, "[Failure]: %s\n", cmd); 256 ERR_print_errors(out); 257 } 258 } 259 } 260 261 int engine_main(int argc, char **argv) 262 { 263 int ret = 1, i; 264 int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; 265 ENGINE *e; 266 STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null(); 267 STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null(); 268 STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null(); 269 BIO *out; 270 const char *indent = " "; 271 OPTION_CHOICE o; 272 char *prog; 273 char *argv1; 274 275 out = dup_bio_out(FORMAT_TEXT); 276 if (engines == NULL || pre_cmds == NULL || post_cmds == NULL) 277 goto end; 278 279 /* Remember the original command name, parse/skip any leading engine 280 * names, and then setup to parse the rest of the line as flags. */ 281 prog = argv[0]; 282 while ((argv1 = argv[1]) != NULL && *argv1 != '-') { 283 sk_OPENSSL_CSTRING_push(engines, argv1); 284 argc--; 285 argv++; 286 } 287 argv[0] = prog; 288 opt_init(argc, argv, engine_options); 289 290 while ((o = opt_next()) != OPT_EOF) { 291 switch (o) { 292 case OPT_EOF: 293 case OPT_ERR: 294 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 295 goto end; 296 case OPT_HELP: 297 opt_help(engine_options); 298 ret = 0; 299 goto end; 300 case OPT_VVVV: 301 case OPT_VVV: 302 case OPT_VV: 303 case OPT_V: 304 /* Convert to an integer from one to four. */ 305 i = (int)(o - OPT_V) + 1; 306 if (verbose < i) 307 verbose = i; 308 break; 309 case OPT_C: 310 list_cap = 1; 311 break; 312 case OPT_TT: 313 test_avail_noise++; 314 /* fall thru */ 315 case OPT_T: 316 test_avail++; 317 break; 318 case OPT_PRE: 319 sk_OPENSSL_STRING_push(pre_cmds, opt_arg()); 320 break; 321 case OPT_POST: 322 sk_OPENSSL_STRING_push(post_cmds, opt_arg()); 323 break; 324 } 325 } 326 327 /* Allow any trailing parameters as engine names. */ 328 argc = opt_num_rest(); 329 argv = opt_rest(); 330 for ( ; *argv; argv++) { 331 if (**argv == '-') { 332 BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n", 333 prog); 334 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 335 goto end; 336 } 337 sk_OPENSSL_CSTRING_push(engines, *argv); 338 } 339 340 if (sk_OPENSSL_CSTRING_num(engines) == 0) { 341 for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { 342 sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e)); 343 } 344 } 345 346 ret = 0; 347 for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) { 348 const char *id = sk_OPENSSL_CSTRING_value(engines, i); 349 if ((e = ENGINE_by_id(id)) != NULL) { 350 const char *name = ENGINE_get_name(e); 351 /* 352 * Do "id" first, then "name". Easier to auto-parse. 353 */ 354 BIO_printf(out, "(%s) %s\n", id, name); 355 util_do_cmds(e, pre_cmds, out, indent); 356 if (strcmp(ENGINE_get_id(e), id) != 0) { 357 BIO_printf(out, "Loaded: (%s) %s\n", 358 ENGINE_get_id(e), ENGINE_get_name(e)); 359 } 360 if (list_cap) { 361 int cap_size = 256; 362 char *cap_buf = NULL; 363 int k, n; 364 const int *nids; 365 ENGINE_CIPHERS_PTR fn_c; 366 ENGINE_DIGESTS_PTR fn_d; 367 ENGINE_PKEY_METHS_PTR fn_pk; 368 369 if (ENGINE_get_RSA(e) != NULL 370 && !append_buf(&cap_buf, &cap_size, "RSA")) 371 goto end; 372 if (ENGINE_get_DSA(e) != NULL 373 && !append_buf(&cap_buf, &cap_size, "DSA")) 374 goto end; 375 if (ENGINE_get_DH(e) != NULL 376 && !append_buf(&cap_buf, &cap_size, "DH")) 377 goto end; 378 if (ENGINE_get_RAND(e) != NULL 379 && !append_buf(&cap_buf, &cap_size, "RAND")) 380 goto end; 381 382 fn_c = ENGINE_get_ciphers(e); 383 if (!fn_c) 384 goto skip_ciphers; 385 n = fn_c(e, NULL, &nids, 0); 386 for (k = 0; k < n; ++k) 387 if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) 388 goto end; 389 390 skip_ciphers: 391 fn_d = ENGINE_get_digests(e); 392 if (!fn_d) 393 goto skip_digests; 394 n = fn_d(e, NULL, &nids, 0); 395 for (k = 0; k < n; ++k) 396 if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) 397 goto end; 398 399 skip_digests: 400 fn_pk = ENGINE_get_pkey_meths(e); 401 if (!fn_pk) 402 goto skip_pmeths; 403 n = fn_pk(e, NULL, &nids, 0); 404 for (k = 0; k < n; ++k) 405 if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k]))) 406 goto end; 407 skip_pmeths: 408 if (cap_buf && (*cap_buf != '\0')) 409 BIO_printf(out, " [%s]\n", cap_buf); 410 411 OPENSSL_free(cap_buf); 412 } 413 if (test_avail) { 414 BIO_printf(out, "%s", indent); 415 if (ENGINE_init(e)) { 416 BIO_printf(out, "[ available ]\n"); 417 util_do_cmds(e, post_cmds, out, indent); 418 ENGINE_finish(e); 419 } else { 420 BIO_printf(out, "[ unavailable ]\n"); 421 if (test_avail_noise) 422 ERR_print_errors_fp(stdout); 423 ERR_clear_error(); 424 } 425 } 426 if ((verbose > 0) && !util_verbose(e, verbose, out, indent)) 427 goto end; 428 ENGINE_free(e); 429 } else { 430 ERR_print_errors(bio_err); 431 /* because exit codes above 127 have special meaning on Unix */ 432 if (++ret > 127) 433 ret = 127; 434 } 435 } 436 437 end: 438 439 ERR_print_errors(bio_err); 440 sk_OPENSSL_CSTRING_free(engines); 441 sk_OPENSSL_STRING_free(pre_cmds); 442 sk_OPENSSL_STRING_free(post_cmds); 443 BIO_free_all(out); 444 return (ret); 445 } 446 #endif 447