00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #ifndef OPENSSL_NO_ENGINE
00060
00061 #include <stdio.h>
00062 #include <stdlib.h>
00063 #include <string.h>
00064 #ifdef OPENSSL_NO_STDIO
00065 #define APPS_WIN16
00066 #endif
00067 #include "apps.h"
00068 #include <openssl/err.h>
00069 #include <openssl/engine.h>
00070 #include <openssl/ssl.h>
00071
00072 #undef PROG
00073 #define PROG engine_main
00074
00075 static const char *engine_usage[]={
00076 "usage: engine opts [engine ...]\n",
00077 " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n",
00078 " -vv will additionally display each command's description\n",
00079 " -vvv will also add the input flags for each command\n",
00080 " -vvvv will also show internal input flags\n",
00081 " -c - for each engine, also list the capabilities\n",
00082 " -t[t] - for each engine, check that they are really available\n",
00083 " -tt will display error trace for unavailable engines\n",
00084 " -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n",
00085 " to load it (if -t is used)\n",
00086 " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n",
00087 " (only used if -t is also provided)\n",
00088 " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n",
00089 " line, or all supported ENGINEs if none are specified.\n",
00090 " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n",
00091 " argument \"/lib/libdriver.so\".\n",
00092 NULL
00093 };
00094
00095 static void identity(void *ptr)
00096 {
00097 return;
00098 }
00099
00100 static int append_buf(char **buf, const char *s, int *size, int step)
00101 {
00102 int l = strlen(s);
00103
00104 if (*buf == NULL)
00105 {
00106 *size = step;
00107 *buf = OPENSSL_malloc(*size);
00108 if (*buf == NULL)
00109 return 0;
00110 **buf = '\0';
00111 }
00112
00113 if (**buf != '\0')
00114 l += 2;
00115
00116 if (strlen(*buf) + strlen(s) >= (unsigned int)*size)
00117 {
00118 *size += step;
00119 *buf = OPENSSL_realloc(*buf, *size);
00120 }
00121
00122 if (*buf == NULL)
00123 return 0;
00124
00125 if (**buf != '\0')
00126 BUF_strlcat(*buf, ", ", *size);
00127 BUF_strlcat(*buf, s, *size);
00128
00129 return 1;
00130 }
00131
00132 static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
00133 {
00134 int started = 0, err = 0;
00135
00136 BIO_printf(bio_out, "%s%s(input flags): ", indent, indent);
00137 if(flags == 0)
00138 {
00139 BIO_printf(bio_out, "<no flags>\n");
00140 return 1;
00141 }
00142
00143
00144 if(flags & ENGINE_CMD_FLAG_INTERNAL)
00145 {
00146 BIO_printf(bio_out, "[Internal] ");
00147 }
00148
00149 if(flags & ENGINE_CMD_FLAG_NUMERIC)
00150 {
00151 if(started)
00152 {
00153 BIO_printf(bio_out, "|");
00154 err = 1;
00155 }
00156 BIO_printf(bio_out, "NUMERIC");
00157 started = 1;
00158 }
00159
00160
00161
00162
00163 if(flags & ENGINE_CMD_FLAG_STRING)
00164 {
00165 if(started)
00166 {
00167 BIO_printf(bio_out, "|");
00168 err = 1;
00169 }
00170 BIO_printf(bio_out, "STRING");
00171 started = 1;
00172 }
00173 if(flags & ENGINE_CMD_FLAG_NO_INPUT)
00174 {
00175 if(started)
00176 {
00177 BIO_printf(bio_out, "|");
00178 err = 1;
00179 }
00180 BIO_printf(bio_out, "NO_INPUT");
00181 started = 1;
00182 }
00183
00184 flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
00185 ~ENGINE_CMD_FLAG_STRING &
00186 ~ENGINE_CMD_FLAG_NO_INPUT &
00187 ~ENGINE_CMD_FLAG_INTERNAL;
00188 if(flags)
00189 {
00190 if(started) BIO_printf(bio_out, "|");
00191 BIO_printf(bio_out, "<0x%04X>", flags);
00192 }
00193 if(err)
00194 BIO_printf(bio_out, " <illegal flags!>");
00195 BIO_printf(bio_out, "\n");
00196 return 1;
00197 }
00198
00199 static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent)
00200 {
00201 static const int line_wrap = 78;
00202 int num;
00203 int ret = 0;
00204 char *name = NULL;
00205 char *desc = NULL;
00206 int flags;
00207 int xpos = 0;
00208 STACK *cmds = NULL;
00209 if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
00210 ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
00211 0, NULL, NULL)) <= 0))
00212 {
00213 #if 0
00214 BIO_printf(bio_out, "%s<no control commands>\n", indent);
00215 #endif
00216 return 1;
00217 }
00218
00219 cmds = sk_new_null();
00220
00221 if(!cmds)
00222 goto err;
00223 do {
00224 int len;
00225
00226 if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
00227 NULL, NULL)) < 0)
00228 goto err;
00229 if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4)
00230 {
00231
00232 if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
00233 NULL, NULL)) <= 0)
00234 goto err;
00235 if((name = OPENSSL_malloc(len + 1)) == NULL)
00236 goto err;
00237 if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
00238 NULL) <= 0)
00239 goto err;
00240
00241 if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
00242 NULL, NULL)) < 0)
00243 goto err;
00244 if(len > 0)
00245 {
00246 if((desc = OPENSSL_malloc(len + 1)) == NULL)
00247 goto err;
00248 if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
00249 NULL) <= 0)
00250 goto err;
00251 }
00252
00253 if(xpos == 0)
00254
00255 xpos = BIO_printf(bio_out, indent);
00256 else
00257
00258 xpos += BIO_printf(bio_out, ", ");
00259 if(verbose == 1)
00260 {
00261
00262 if((xpos > (int)strlen(indent)) &&
00263 (xpos + (int)strlen(name) > line_wrap))
00264 {
00265 BIO_printf(bio_out, "\n");
00266 xpos = BIO_printf(bio_out, indent);
00267 }
00268 xpos += BIO_printf(bio_out, "%s", name);
00269 }
00270 else
00271 {
00272
00273 BIO_printf(bio_out, "%s: %s\n", name,
00274 (desc == NULL) ? "<no description>" : desc);
00275
00276 if((verbose >= 3) && !util_flags(bio_out, flags,
00277 indent))
00278 goto err;
00279 xpos = 0;
00280 }
00281 }
00282 OPENSSL_free(name); name = NULL;
00283 if(desc) { OPENSSL_free(desc); desc = NULL; }
00284
00285 num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE,
00286 num, NULL, NULL);
00287 } while(num > 0);
00288 if(xpos > 0)
00289 BIO_printf(bio_out, "\n");
00290 ret = 1;
00291 err:
00292 if(cmds) sk_pop_free(cmds, identity);
00293 if(name) OPENSSL_free(name);
00294 if(desc) OPENSSL_free(desc);
00295 return ret;
00296 }
00297
00298 static void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent)
00299 {
00300 int loop, res, num = sk_num(cmds);
00301 if(num < 0)
00302 {
00303 BIO_printf(bio_out, "[Error]: internal stack error\n");
00304 return;
00305 }
00306 for(loop = 0; loop < num; loop++)
00307 {
00308 char buf[256];
00309 const char *cmd, *arg;
00310 cmd = sk_value(cmds, loop);
00311 res = 1;
00312
00313 if((arg = strstr(cmd, ":")) == NULL)
00314 {
00315 if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
00316 res = 0;
00317 }
00318 else
00319 {
00320 if((int)(arg - cmd) > 254)
00321 {
00322 BIO_printf(bio_out,"[Error]: command name too long\n");
00323 return;
00324 }
00325 memcpy(buf, cmd, (int)(arg - cmd));
00326 buf[arg-cmd] = '\0';
00327 arg++;
00328
00329 if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
00330 res = 0;
00331 }
00332 if(res)
00333 BIO_printf(bio_out, "[Success]: %s\n", cmd);
00334 else
00335 {
00336 BIO_printf(bio_out, "[Failure]: %s\n", cmd);
00337 ERR_print_errors(bio_out);
00338 }
00339 }
00340 }
00341
00342 int MAIN(int, char **);
00343
00344 int MAIN(int argc, char **argv)
00345 {
00346 int ret=1,i;
00347 const char **pp;
00348 int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0;
00349 ENGINE *e;
00350 STACK *engines = sk_new_null();
00351 STACK *pre_cmds = sk_new_null();
00352 STACK *post_cmds = sk_new_null();
00353 int badops=1;
00354 BIO *bio_out=NULL;
00355 const char *indent = " ";
00356
00357 apps_startup();
00358 SSL_load_error_strings();
00359
00360 if (bio_err == NULL)
00361 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
00362
00363 if (!load_config(bio_err, NULL))
00364 goto end;
00365 bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
00366 #ifdef OPENSSL_SYS_VMS
00367 {
00368 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
00369 bio_out = BIO_push(tmpbio, bio_out);
00370 }
00371 #endif
00372
00373 argc--;
00374 argv++;
00375 while (argc >= 1)
00376 {
00377 if (strncmp(*argv,"-v",2) == 0)
00378 {
00379 if(strspn(*argv + 1, "v") < strlen(*argv + 1))
00380 goto skip_arg_loop;
00381 if((verbose=strlen(*argv + 1)) > 4)
00382 goto skip_arg_loop;
00383 }
00384 else if (strcmp(*argv,"-c") == 0)
00385 list_cap=1;
00386 else if (strncmp(*argv,"-t",2) == 0)
00387 {
00388 test_avail=1;
00389 if(strspn(*argv + 1, "t") < strlen(*argv + 1))
00390 goto skip_arg_loop;
00391 if((test_avail_noise = strlen(*argv + 1) - 1) > 1)
00392 goto skip_arg_loop;
00393 }
00394 else if (strcmp(*argv,"-pre") == 0)
00395 {
00396 argc--; argv++;
00397 if (argc == 0)
00398 goto skip_arg_loop;
00399 sk_push(pre_cmds,*argv);
00400 }
00401 else if (strcmp(*argv,"-post") == 0)
00402 {
00403 argc--; argv++;
00404 if (argc == 0)
00405 goto skip_arg_loop;
00406 sk_push(post_cmds,*argv);
00407 }
00408 else if ((strncmp(*argv,"-h",2) == 0) ||
00409 (strcmp(*argv,"-?") == 0))
00410 goto skip_arg_loop;
00411 else
00412 sk_push(engines,*argv);
00413 argc--;
00414 argv++;
00415 }
00416
00417 badops = 0;
00418 skip_arg_loop:
00419
00420 if (badops)
00421 {
00422 for (pp=engine_usage; (*pp != NULL); pp++)
00423 BIO_printf(bio_err,"%s",*pp);
00424 goto end;
00425 }
00426
00427 if (sk_num(engines) == 0)
00428 {
00429 for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
00430 {
00431 sk_push(engines,(char *)ENGINE_get_id(e));
00432 }
00433 }
00434
00435 for (i=0; i<sk_num(engines); i++)
00436 {
00437 const char *id = sk_value(engines,i);
00438 if ((e = ENGINE_by_id(id)) != NULL)
00439 {
00440 const char *name = ENGINE_get_name(e);
00441
00442 BIO_printf(bio_out, "(%s) %s\n", id, name);
00443 util_do_cmds(e, pre_cmds, bio_out, indent);
00444 if (strcmp(ENGINE_get_id(e), id) != 0)
00445 {
00446 BIO_printf(bio_out, "Loaded: (%s) %s\n",
00447 ENGINE_get_id(e), ENGINE_get_name(e));
00448 }
00449 if (list_cap)
00450 {
00451 int cap_size = 256;
00452 char *cap_buf = NULL;
00453 int k,n;
00454 const int *nids;
00455 ENGINE_CIPHERS_PTR fn_c;
00456 ENGINE_DIGESTS_PTR fn_d;
00457
00458 if (ENGINE_get_RSA(e) != NULL
00459 && !append_buf(&cap_buf, "RSA",
00460 &cap_size, 256))
00461 goto end;
00462 if (ENGINE_get_DSA(e) != NULL
00463 && !append_buf(&cap_buf, "DSA",
00464 &cap_size, 256))
00465 goto end;
00466 if (ENGINE_get_DH(e) != NULL
00467 && !append_buf(&cap_buf, "DH",
00468 &cap_size, 256))
00469 goto end;
00470 if (ENGINE_get_RAND(e) != NULL
00471 && !append_buf(&cap_buf, "RAND",
00472 &cap_size, 256))
00473 goto end;
00474
00475 fn_c = ENGINE_get_ciphers(e);
00476 if(!fn_c) goto skip_ciphers;
00477 n = fn_c(e, NULL, &nids, 0);
00478 for(k=0 ; k < n ; ++k)
00479 if(!append_buf(&cap_buf,
00480 OBJ_nid2sn(nids[k]),
00481 &cap_size, 256))
00482 goto end;
00483
00484 skip_ciphers:
00485 fn_d = ENGINE_get_digests(e);
00486 if(!fn_d) goto skip_digests;
00487 n = fn_d(e, NULL, &nids, 0);
00488 for(k=0 ; k < n ; ++k)
00489 if(!append_buf(&cap_buf,
00490 OBJ_nid2sn(nids[k]),
00491 &cap_size, 256))
00492 goto end;
00493
00494 skip_digests:
00495 if (cap_buf && (*cap_buf != '\0'))
00496 BIO_printf(bio_out, " [%s]\n", cap_buf);
00497
00498 OPENSSL_free(cap_buf);
00499 }
00500 if(test_avail)
00501 {
00502 BIO_printf(bio_out, "%s", indent);
00503 if (ENGINE_init(e))
00504 {
00505 BIO_printf(bio_out, "[ available ]\n");
00506 util_do_cmds(e, post_cmds, bio_out, indent);
00507 ENGINE_finish(e);
00508 }
00509 else
00510 {
00511 BIO_printf(bio_out, "[ unavailable ]\n");
00512 if(test_avail_noise)
00513 ERR_print_errors_fp(stdout);
00514 ERR_clear_error();
00515 }
00516 }
00517 if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
00518 goto end;
00519 ENGINE_free(e);
00520 }
00521 else
00522 ERR_print_errors(bio_err);
00523 }
00524
00525 ret=0;
00526 end:
00527
00528 ERR_print_errors(bio_err);
00529 sk_pop_free(engines, identity);
00530 sk_pop_free(pre_cmds, identity);
00531 sk_pop_free(post_cmds, identity);
00532 if (bio_out != NULL) BIO_free_all(bio_out);
00533 apps_shutdown();
00534 OPENSSL_EXIT(ret);
00535 }
00536 #else
00537
00538 # if PEDANTIC
00539 static void *dummy=&dummy;
00540 # endif
00541
00542 #endif