]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/engine.c
Rename some BUF_xxx to OPENSSL_xxx
[thirdparty/openssl.git] / apps / engine.c
CommitLineData
0f113f3e
MC
1/*
2 * Written by Richard Levitte <richard@levitte.org> for the OpenSSL project
3 * 2000.
14c6d27d
RL
4 */
5/* ====================================================================
6 * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
0f113f3e 13 * notice, this list of conditions and the following disclaimer.
14c6d27d
RL
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
14c6d27d
RL
62#include "apps.h"
63#include <openssl/err.h>
70531c14 64#ifndef OPENSSL_NO_ENGINE
0f113f3e
MC
65# include <openssl/engine.h>
66# include <openssl/ssl.h>
67
7e1b7485
RS
68typedef enum OPTION_choice {
69 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
70 OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
71 OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
72} OPTION_CHOICE;
73
74OPTIONS engine_options[] = {
75 {"help", OPT_HELP, '-', "Display this summary"},
76 {"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
77 {"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
78 {"vv", OPT_VV, '-', "Also display each command's description"},
79 {"v", OPT_V, '-', "For each engine, list its 'control commands'"},
80 {"c", OPT_C, '-', "List the capabilities of each engine"},
81 {"t", OPT_T, '-', "Check that each engine is available"},
82 {"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
83 {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
84 {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
85 {OPT_MORE_STR, OPT_EOF, 1,
86 "Commands are like \"SO_PATH:/lib/libdriver.so\""},
87 {NULL}
14c6d27d
RL
88};
89
5ce278a7 90static void identity(char *ptr)
0f113f3e
MC
91{
92 return;
93}
14c6d27d 94
354c3ace 95static int append_buf(char **buf, const char *s, int *size, int step)
0f113f3e 96{
0f113f3e
MC
97 if (*buf == NULL) {
98 *size = step;
68dc6824 99 *buf = app_malloc(*size, "engine buffer");
0f113f3e
MC
100 **buf = '\0';
101 }
69e7805f 102
0f113f3e
MC
103 if (strlen(*buf) + strlen(s) >= (unsigned int)*size) {
104 *size += step;
105 *buf = OPENSSL_realloc(*buf, *size);
106 }
69e7805f 107
0f113f3e
MC
108 if (*buf == NULL)
109 return 0;
69e7805f 110
0f113f3e 111 if (**buf != '\0')
7644a9ae
RS
112 OPENSSL_strlcat(*buf, ", ", *size);
113 OPENSSL_strlcat(*buf, s, *size);
69e7805f 114
0f113f3e
MC
115 return 1;
116}
69e7805f 117
7e1b7485 118static int util_flags(BIO *out, unsigned int flags, const char *indent)
0f113f3e
MC
119{
120 int started = 0, err = 0;
121 /* Indent before displaying input flags */
7e1b7485 122 BIO_printf(out, "%s%s(input flags): ", indent, indent);
0f113f3e 123 if (flags == 0) {
7e1b7485 124 BIO_printf(out, "<no flags>\n");
0f113f3e
MC
125 return 1;
126 }
127 /*
128 * If the object is internal, mark it in a way that shows instead of
129 * having it part of all the other flags, even if it really is.
130 */
131 if (flags & ENGINE_CMD_FLAG_INTERNAL) {
7e1b7485 132 BIO_printf(out, "[Internal] ");
0f113f3e
MC
133 }
134
135 if (flags & ENGINE_CMD_FLAG_NUMERIC) {
7e1b7485 136 BIO_printf(out, "NUMERIC");
0f113f3e
MC
137 started = 1;
138 }
139 /*
140 * Now we check that no combinations of the mutually exclusive NUMERIC,
141 * STRING, and NO_INPUT flags have been used. Future flags that can be
142 * OR'd together with these would need to added after these to preserve
143 * the testing logic.
144 */
145 if (flags & ENGINE_CMD_FLAG_STRING) {
146 if (started) {
7e1b7485 147 BIO_printf(out, "|");
0f113f3e
MC
148 err = 1;
149 }
7e1b7485 150 BIO_printf(out, "STRING");
0f113f3e
MC
151 started = 1;
152 }
153 if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
154 if (started) {
7e1b7485 155 BIO_printf(out, "|");
0f113f3e
MC
156 err = 1;
157 }
7e1b7485 158 BIO_printf(out, "NO_INPUT");
0f113f3e
MC
159 started = 1;
160 }
161 /* Check for unknown flags */
162 flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
163 ~ENGINE_CMD_FLAG_STRING &
164 ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL;
165 if (flags) {
166 if (started)
7e1b7485
RS
167 BIO_printf(out, "|");
168 BIO_printf(out, "<0x%04X>", flags);
0f113f3e
MC
169 }
170 if (err)
7e1b7485
RS
171 BIO_printf(out, " <illegal flags!>");
172 BIO_printf(out, "\n");
0f113f3e
MC
173 return 1;
174}
175
7e1b7485 176static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent)
0f113f3e
MC
177{
178 static const int line_wrap = 78;
179 int num;
180 int ret = 0;
181 char *name = NULL;
182 char *desc = NULL;
183 int flags;
184 int xpos = 0;
185 STACK_OF(OPENSSL_STRING) *cmds = NULL;
186 if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
187 ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
188 0, NULL, NULL)) <= 0)) {
0f113f3e
MC
189 return 1;
190 }
191
192 cmds = sk_OPENSSL_STRING_new_null();
0f113f3e
MC
193 if (!cmds)
194 goto err;
7e1b7485 195
0f113f3e
MC
196 do {
197 int len;
198 /* Get the command input flags */
199 if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
200 NULL, NULL)) < 0)
201 goto err;
202 if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) {
203 /* Get the command name */
204 if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
205 NULL, NULL)) <= 0)
206 goto err;
68dc6824 207 name = app_malloc(len + 1, "name buffer");
0f113f3e
MC
208 if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
209 NULL) <= 0)
210 goto err;
211 /* Get the command description */
212 if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
213 NULL, NULL)) < 0)
214 goto err;
215 if (len > 0) {
68dc6824 216 desc = app_malloc(len + 1, "description buffer");
0f113f3e 217 if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
2cd3ad9b 218 NULL) <= 0)
0f113f3e
MC
219 goto err;
220 }
221 /* Now decide on the output */
222 if (xpos == 0)
223 /* Do an indent */
7e1b7485 224 xpos = BIO_puts(out, indent);
0f113f3e
MC
225 else
226 /* Otherwise prepend a ", " */
7e1b7485 227 xpos += BIO_printf(out, ", ");
0f113f3e
MC
228 if (verbose == 1) {
229 /*
230 * We're just listing names, comma-delimited
231 */
232 if ((xpos > (int)strlen(indent)) &&
233 (xpos + (int)strlen(name) > line_wrap)) {
7e1b7485
RS
234 BIO_printf(out, "\n");
235 xpos = BIO_puts(out, indent);
0f113f3e 236 }
7e1b7485 237 xpos += BIO_printf(out, "%s", name);
0f113f3e
MC
238 } else {
239 /* We're listing names plus descriptions */
7e1b7485 240 BIO_printf(out, "%s: %s\n", name,
0f113f3e
MC
241 (desc == NULL) ? "<no description>" : desc);
242 /* ... and sometimes input flags */
7e1b7485 243 if ((verbose >= 3) && !util_flags(out, flags, indent))
0f113f3e
MC
244 goto err;
245 xpos = 0;
246 }
247 }
248 OPENSSL_free(name);
249 name = NULL;
b548a1f1
RS
250 OPENSSL_free(desc);
251 desc = NULL;
0f113f3e
MC
252 /* Move to the next command */
253 num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL);
254 } while (num > 0);
255 if (xpos > 0)
7e1b7485 256 BIO_printf(out, "\n");
0f113f3e
MC
257 ret = 1;
258 err:
25aaa98a 259 sk_OPENSSL_STRING_pop_free(cmds, identity);
b548a1f1
RS
260 OPENSSL_free(name);
261 OPENSSL_free(desc);
0f113f3e
MC
262 return ret;
263}
f11bc840 264
c869da88 265static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
7e1b7485 266 BIO *out, const char *indent)
0f113f3e
MC
267{
268 int loop, res, num = sk_OPENSSL_STRING_num(cmds);
269
270 if (num < 0) {
7e1b7485 271 BIO_printf(out, "[Error]: internal stack error\n");
0f113f3e
MC
272 return;
273 }
274 for (loop = 0; loop < num; loop++) {
275 char buf[256];
276 const char *cmd, *arg;
277 cmd = sk_OPENSSL_STRING_value(cmds, loop);
278 res = 1; /* assume success */
279 /* Check if this command has no ":arg" */
280 if ((arg = strstr(cmd, ":")) == NULL) {
281 if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
282 res = 0;
283 } else {
284 if ((int)(arg - cmd) > 254) {
7e1b7485 285 BIO_printf(out, "[Error]: command name too long\n");
0f113f3e
MC
286 return;
287 }
288 memcpy(buf, cmd, (int)(arg - cmd));
289 buf[arg - cmd] = '\0';
290 arg++; /* Move past the ":" */
291 /* Call the command with the argument */
292 if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
293 res = 0;
294 }
295 if (res)
7e1b7485 296 BIO_printf(out, "[Success]: %s\n", cmd);
0f113f3e 297 else {
7e1b7485
RS
298 BIO_printf(out, "[Failure]: %s\n", cmd);
299 ERR_print_errors(out);
0f113f3e
MC
300 }
301 }
302}
f11bc840 303
7e1b7485 304int engine_main(int argc, char **argv)
0f113f3e
MC
305{
306 int ret = 1, i;
0f113f3e
MC
307 int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
308 ENGINE *e;
309 STACK_OF(OPENSSL_STRING) *engines = sk_OPENSSL_STRING_new_null();
310 STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null();
311 STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null();
7e1b7485 312 BIO *out;
0f113f3e 313 const char *indent = " ";
7e1b7485
RS
314 OPTION_CHOICE o;
315 char *prog;
0f113f3e 316
a60994df 317 out = dup_bio_out(FORMAT_TEXT);
7e1b7485
RS
318 prog = opt_init(argc, argv, engine_options);
319 if (!engines || !pre_cmds || !post_cmds)
0f113f3e 320 goto end;
7e1b7485
RS
321 while ((o = opt_next()) != OPT_EOF) {
322 switch (o) {
323 case OPT_EOF:
324 case OPT_ERR:
325 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
326 goto end;
327 case OPT_HELP:
328 opt_help(engine_options);
329 ret = 0;
330 goto end;
331 case OPT_VVVV:
332 case OPT_VVV:
333 case OPT_VV:
334 case OPT_V:
335 /* Convert to an integer from one to four. */
336 i = (int)(o - OPT_V) + 1;
337 if (verbose < i)
338 verbose = i;
339 break;
340 case OPT_C:
0f113f3e 341 list_cap = 1;
7e1b7485
RS
342 break;
343 case OPT_TT:
344 test_avail_noise++;
345 case OPT_T:
346 test_avail++;
347 break;
348 case OPT_PRE:
349 sk_OPENSSL_STRING_push(pre_cmds, opt_arg());
350 break;
351 case OPT_POST:
352 sk_OPENSSL_STRING_push(post_cmds, opt_arg());
353 break;
354 }
0f113f3e 355 }
7e1b7485
RS
356 argc = opt_num_rest();
357 argv = opt_rest();
358 for ( ; *argv; argv++)
359 sk_OPENSSL_STRING_push(engines, *argv);
0f113f3e
MC
360
361 if (sk_OPENSSL_STRING_num(engines) == 0) {
362 for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
363 sk_OPENSSL_STRING_push(engines, (char *)ENGINE_get_id(e));
364 }
365 }
366
367 for (i = 0; i < sk_OPENSSL_STRING_num(engines); i++) {
368 const char *id = sk_OPENSSL_STRING_value(engines, i);
369 if ((e = ENGINE_by_id(id)) != NULL) {
370 const char *name = ENGINE_get_name(e);
371 /*
372 * Do "id" first, then "name". Easier to auto-parse.
373 */
7e1b7485
RS
374 BIO_printf(out, "(%s) %s\n", id, name);
375 util_do_cmds(e, pre_cmds, out, indent);
0f113f3e 376 if (strcmp(ENGINE_get_id(e), id) != 0) {
7e1b7485 377 BIO_printf(out, "Loaded: (%s) %s\n",
0f113f3e
MC
378 ENGINE_get_id(e), ENGINE_get_name(e));
379 }
380 if (list_cap) {
381 int cap_size = 256;
382 char *cap_buf = NULL;
383 int k, n;
384 const int *nids;
385 ENGINE_CIPHERS_PTR fn_c;
386 ENGINE_DIGESTS_PTR fn_d;
387 ENGINE_PKEY_METHS_PTR fn_pk;
388
389 if (ENGINE_get_RSA(e) != NULL
390 && !append_buf(&cap_buf, "RSA", &cap_size, 256))
391 goto end;
392 if (ENGINE_get_DSA(e) != NULL
393 && !append_buf(&cap_buf, "DSA", &cap_size, 256))
394 goto end;
395 if (ENGINE_get_DH(e) != NULL
396 && !append_buf(&cap_buf, "DH", &cap_size, 256))
397 goto end;
398 if (ENGINE_get_RAND(e) != NULL
399 && !append_buf(&cap_buf, "RAND", &cap_size, 256))
400 goto end;
401
402 fn_c = ENGINE_get_ciphers(e);
403 if (!fn_c)
404 goto skip_ciphers;
405 n = fn_c(e, NULL, &nids, 0);
406 for (k = 0; k < n; ++k)
407 if (!append_buf(&cap_buf,
408 OBJ_nid2sn(nids[k]), &cap_size, 256))
409 goto end;
410
411 skip_ciphers:
412 fn_d = ENGINE_get_digests(e);
413 if (!fn_d)
414 goto skip_digests;
415 n = fn_d(e, NULL, &nids, 0);
416 for (k = 0; k < n; ++k)
417 if (!append_buf(&cap_buf,
418 OBJ_nid2sn(nids[k]), &cap_size, 256))
419 goto end;
420
421 skip_digests:
422 fn_pk = ENGINE_get_pkey_meths(e);
423 if (!fn_pk)
424 goto skip_pmeths;
425 n = fn_pk(e, NULL, &nids, 0);
426 for (k = 0; k < n; ++k)
427 if (!append_buf(&cap_buf,
428 OBJ_nid2sn(nids[k]), &cap_size, 256))
429 goto end;
430 skip_pmeths:
431 if (cap_buf && (*cap_buf != '\0'))
7e1b7485 432 BIO_printf(out, " [%s]\n", cap_buf);
0f113f3e
MC
433
434 OPENSSL_free(cap_buf);
435 }
436 if (test_avail) {
7e1b7485 437 BIO_printf(out, "%s", indent);
0f113f3e 438 if (ENGINE_init(e)) {
7e1b7485
RS
439 BIO_printf(out, "[ available ]\n");
440 util_do_cmds(e, post_cmds, out, indent);
0f113f3e
MC
441 ENGINE_finish(e);
442 } else {
7e1b7485 443 BIO_printf(out, "[ unavailable ]\n");
0f113f3e
MC
444 if (test_avail_noise)
445 ERR_print_errors_fp(stdout);
446 ERR_clear_error();
447 }
448 }
7e1b7485 449 if ((verbose > 0) && !util_verbose(e, verbose, out, indent))
0f113f3e
MC
450 goto end;
451 ENGINE_free(e);
452 } else
453 ERR_print_errors(bio_err);
454 }
455
456 ret = 0;
457 end:
458
459 ERR_print_errors(bio_err);
460 sk_OPENSSL_STRING_pop_free(engines, identity);
461 sk_OPENSSL_STRING_pop_free(pre_cmds, identity);
462 sk_OPENSSL_STRING_pop_free(post_cmds, identity);
7e1b7485
RS
463 BIO_free_all(out);
464 return (ret);
0f113f3e 465}
12d4e7b8
DSH
466#else
467
468# if PEDANTIC
0f113f3e 469static void *dummy = &dummy;
12d4e7b8
DSH
470# endif
471
0b13e9f0 472#endif