1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59: #ifndef OPENSSL_NO_ENGINE
60:
61: #include <stdio.h>
62: #include <stdlib.h>
63: #include <string.h>
64: #ifdef OPENSSL_NO_STDIO
65: #define APPS_WIN16
66: #endif
67: #include "apps.h"
68: #include <openssl/err.h>
69: #include <openssl/engine.h>
70: #include <openssl/ssl.h>
71:
72: #undef PROG
73: #define PROG engine_main
74:
75: static const char *engine_usage[]={
76: "usage: engine opts [engine ...]\n",
77: " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n",
78: " -vv will additionally display each command's description\n",
79: " -vvv will also add the input flags for each command\n",
80: " -vvvv will also show internal input flags\n",
81: " -c - for each engine, also list the capabilities\n",
82: " -t[t] - for each engine, check that they are really available\n",
83: " -tt will display error trace for unavailable engines\n",
84: " -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n",
85: " to load it (if -t is used)\n",
86: " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n",
87: " (only used if -t is also provided)\n",
88: " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n",
89: " line, or all supported ENGINEs if none are specified.\n",
90: " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n",
91: " argument \"/lib/libdriver.so\".\n",
92: NULL
93: };
94:
95: static void identity(void *ptr)
96: {
97: return;
98: }
99:
100: static int append_buf(char **buf, const char *s, int *size, int step)
101: {
102: int l = strlen(s);
103:
104: if (*buf == NULL)
105: {
106: *size = step;
107: *buf = OPENSSL_malloc(*size);
108: if (*buf == NULL)
109: return 0;
110: **buf = '\0';
111: }
112:
113: if (**buf != '\0')
114: l += 2;
115:
116: if (strlen(*buf) + strlen(s) >= (unsigned int)*size)
117: {
118: *size += step;
119: *buf = OPENSSL_realloc(*buf, *size);
120: }
121:
122: if (*buf == NULL)
123: return 0;
124:
125: if (**buf != '\0')
126: BUF_strlcat(*buf, ", ", *size);
127: BUF_strlcat(*buf, s, *size);
128:
129: return 1;
130: }
131:
132: static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
133: {
134: int started = 0, err = 0;
135:
136: BIO_printf(bio_out, "%s%s(input flags): ", indent, indent);
137: if(flags == 0)
138: {
139: BIO_printf(bio_out, "<no flags>\n");
140: return 1;
141: }
142:
143:
144: if(flags & ENGINE_CMD_FLAG_INTERNAL)
145: {
146: BIO_printf(bio_out, "[Internal] ");
147: }
148:
149: if(flags & ENGINE_CMD_FLAG_NUMERIC)
150: {
151: if(started)
152: {
153: BIO_printf(bio_out, "|");
154: err = 1;
155: }
156: BIO_printf(bio_out, "NUMERIC");
157: started = 1;
158: }
159:
160:
161:
162:
163: if(flags & ENGINE_CMD_FLAG_STRING)
164: {
165: if(started)
166: {
167: BIO_printf(bio_out, "|");
168: err = 1;
169: }
170: BIO_printf(bio_out, "STRING");
171: started = 1;
172: }
173: if(flags & ENGINE_CMD_FLAG_NO_INPUT)
174: {
175: if(started)
176: {
177: BIO_printf(bio_out, "|");
178: err = 1;
179: }
180: BIO_printf(bio_out, "NO_INPUT");
181: started = 1;
182: }
183:
184: flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
185: ~ENGINE_CMD_FLAG_STRING &
186: ~ENGINE_CMD_FLAG_NO_INPUT &
187: ~ENGINE_CMD_FLAG_INTERNAL;
188: if(flags)
189: {
190: if(started) BIO_printf(bio_out, "|");
191: BIO_printf(bio_out, "<0x%04X>", flags);
192: }
193: if(err)
194: BIO_printf(bio_out, " <illegal flags!>");
195: BIO_printf(bio_out, "\n");
196: return 1;
197: }
198:
199: static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent)
200: {
201: static const int line_wrap = 78;
202: int num;
203: int ret = 0;
204: char *name = NULL;
205: char *desc = NULL;
206: int flags;
207: int xpos = 0;
208: STACK *cmds = NULL;
209: if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
210: ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
211: 0, NULL, NULL)) <= 0))
212: {
213: #if 0
214: BIO_printf(bio_out, "%s<no control commands>\n", indent);
215: #endif
216: return 1;
217: }
218:
219: cmds = sk_new_null();
220:
221: if(!cmds)
222: goto err;
223: do {
224: int len;
225:
226: if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
227: NULL, NULL)) < 0)
228: goto err;
229: if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4)
230: {
231:
232: if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
233: NULL, NULL)) <= 0)
234: goto err;
235: if((name = OPENSSL_malloc(len + 1)) == NULL)
236: goto err;
237: if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
238: NULL) <= 0)
239: goto err;
240:
241: if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
242: NULL, NULL)) < 0)
243: goto err;
244: if(len > 0)
245: {
246: if((desc = OPENSSL_malloc(len + 1)) == NULL)
247: goto err;
248: if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
249: NULL) <= 0)
250: goto err;
251: }
252:
253: if(xpos == 0)
254:
255: xpos = BIO_printf(bio_out, indent);
256: else
257:
258: xpos += BIO_printf(bio_out, ", ");
259: if(verbose == 1)
260: {
261:
262: if((xpos > (int)strlen(indent)) &&
263: (xpos + (int)strlen(name) > line_wrap))
264: {
265: BIO_printf(bio_out, "\n");
266: xpos = BIO_printf(bio_out, indent);
267: }
268: xpos += BIO_printf(bio_out, "%s", name);
269: }
270: else
271: {
272:
273: BIO_printf(bio_out, "%s: %s\n", name,
274: (desc == NULL) ? "<no description>" : desc);
275:
276: if((verbose >= 3) && !util_flags(bio_out, flags,
277: indent))
278: goto err;
279: xpos = 0;
280: }
281: }
282: OPENSSL_free(name); name = NULL;
283: if(desc) { OPENSSL_free(desc); desc = NULL; }
284:
285: num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE,
286: num, NULL, NULL);
287: } while(num > 0);
288: if(xpos > 0)
289: BIO_printf(bio_out, "\n");
290: ret = 1;
291: err:
292: if(cmds) sk_pop_free(cmds, identity);
293: if(name) OPENSSL_free(name);
294: if(desc) OPENSSL_free(desc);
295: return ret;
296: }
297:
298: static void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent)
299: {
300: int loop, res, num = sk_num(cmds);
301: if(num < 0)
302: {
303: BIO_printf(bio_out, "[Error]: internal stack error\n");
304: return;
305: }
306: for(loop = 0; loop < num; loop++)
307: {
308: char buf[256];
309: const char *cmd, *arg;
310: cmd = sk_value(cmds, loop);
311: res = 1;
312:
313: if((arg = strstr(cmd, ":")) == NULL)
314: {
315: if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
316: res = 0;
317: }
318: else
319: {
320: if((int)(arg - cmd) > 254)
321: {
322: BIO_printf(bio_out,"[Error]: command name too long\n");
323: return;
324: }
325: memcpy(buf, cmd, (int)(arg - cmd));
326: buf[arg-cmd] = '\0';
327: arg++;
328:
329: if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
330: res = 0;
331: }
332: if(res)
333: BIO_printf(bio_out, "[Success]: %s\n", cmd);
334: else
335: {
336: BIO_printf(bio_out, "[Failure]: %s\n", cmd);
337: ERR_print_errors(bio_out);
338: }
339: }
340: }
341:
342: int MAIN(int, char **);
343:
344: int MAIN(int argc, char **argv)
345: {
346: int ret=1,i;
347: const char **pp;
348: int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0;
349: ENGINE *e;
350: STACK *engines = sk_new_null();
351: STACK *pre_cmds = sk_new_null();
352: STACK *post_cmds = sk_new_null();
353: int badops=1;
354: BIO *bio_out=NULL;
355: const char *indent = " ";
356:
357: apps_startup();
358: SSL_load_error_strings();
359:
360: if (bio_err == NULL)
361: bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
362:
363: if (!load_config(bio_err, NULL))
364: goto end;
365: bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
366: #ifdef OPENSSL_SYS_VMS
367: {
368: BIO *tmpbio = BIO_new(BIO_f_linebuffer());
369: bio_out = BIO_push(tmpbio, bio_out);
370: }
371: #endif
372:
373: argc--;
374: argv++;
375: while (argc >= 1)
376: {
377: if (strncmp(*argv,"-v",2) == 0)
378: {
379: if(strspn(*argv + 1, "v") < strlen(*argv + 1))
380: goto skip_arg_loop;
381: if((verbose=strlen(*argv + 1)) > 4)
382: goto skip_arg_loop;
383: }
384: else if (strcmp(*argv,"-c") == 0)
385: list_cap=1;
386: else if (strncmp(*argv,"-t",2) == 0)
387: {
388: test_avail=1;
389: if(strspn(*argv + 1, "t") < strlen(*argv + 1))
390: goto skip_arg_loop;
391: if((test_avail_noise = strlen(*argv + 1) - 1) > 1)
392: goto skip_arg_loop;
393: }
394: else if (strcmp(*argv,"-pre") == 0)
395: {
396: argc--; argv++;
397: if (argc == 0)
398: goto skip_arg_loop;
399: sk_push(pre_cmds,*argv);
400: }
401: else if (strcmp(*argv,"-post") == 0)
402: {
403: argc--; argv++;
404: if (argc == 0)
405: goto skip_arg_loop;
406: sk_push(post_cmds,*argv);
407: }
408: else if ((strncmp(*argv,"-h",2) == 0) ||
409: (strcmp(*argv,"-?") == 0))
410: goto skip_arg_loop;
411: else
412: sk_push(engines,*argv);
413: argc--;
414: argv++;
415: }
416:
417: badops = 0;
418: skip_arg_loop:
419:
420: if (badops)
421: {
422: for (pp=engine_usage; (*pp != NULL); pp++)
423: BIO_printf(bio_err,"%s",*pp);
424: goto end;
425: }
426:
427: if (sk_num(engines) == 0)
428: {
429: for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
430: {
431: sk_push(engines,(char *)ENGINE_get_id(e));
432: }
433: }
434:
435: for (i=0; i<sk_num(engines); i++)
436: {
437: const char *id = sk_value(engines,i);
438: if ((e = ENGINE_by_id(id)) != NULL)
439: {
440: const char *name = ENGINE_get_name(e);
441:
442: BIO_printf(bio_out, "(%s) %s\n", id, name);
443: util_do_cmds(e, pre_cmds, bio_out, indent);
444: if (strcmp(ENGINE_get_id(e), id) != 0)
445: {
446: BIO_printf(bio_out, "Loaded: (%s) %s\n",
447: ENGINE_get_id(e), ENGINE_get_name(e));
448: }
449: if (list_cap)
450: {
451: int cap_size = 256;
452: char *cap_buf = NULL;
453: int k,n;
454: const int *nids;
455: ENGINE_CIPHERS_PTR fn_c;
456: ENGINE_DIGESTS_PTR fn_d;
457:
458: if (ENGINE_get_RSA(e) != NULL
459: && !append_buf(&cap_buf, "RSA",
460: &cap_size, 256))
461: goto end;
462: if (ENGINE_get_DSA(e) != NULL
463: && !append_buf(&cap_buf, "DSA",
464: &cap_size, 256))
465: goto end;
466: if (ENGINE_get_DH(e) != NULL
467: && !append_buf(&cap_buf, "DH",
468: &cap_size, 256))
469: goto end;
470: if (ENGINE_get_RAND(e) != NULL
471: && !append_buf(&cap_buf, "RAND",
472: &cap_size, 256))
473: goto end;
474:
475: fn_c = ENGINE_get_ciphers(e);
476: if(!fn_c) goto skip_ciphers;
477: n = fn_c(e, NULL, &nids, 0);
478: for(k=0 ; k < n ; ++k)
479: if(!append_buf(&cap_buf,
480: OBJ_nid2sn(nids[k]),
481: &cap_size, 256))
482: goto end;
483:
484: skip_ciphers:
485: fn_d = ENGINE_get_digests(e);
486: if(!fn_d) goto skip_digests;
487: n = fn_d(e, NULL, &nids, 0);
488: for(k=0 ; k < n ; ++k)
489: if(!append_buf(&cap_buf,
490: OBJ_nid2sn(nids[k]),
491: &cap_size, 256))
492: goto end;
493:
494: skip_digests:
495: if (cap_buf && (*cap_buf != '\0'))
496: BIO_printf(bio_out, " [%s]\n", cap_buf);
497:
498: OPENSSL_free(cap_buf);
499: }
500: if(test_avail)
501: {
502: BIO_printf(bio_out, "%s", indent);
503: if (ENGINE_init(e))
504: {
505: BIO_printf(bio_out, "[ available ]\n");
506: util_do_cmds(e, post_cmds, bio_out, indent);
507: ENGINE_finish(e);
508: }
509: else
510: {
511: BIO_printf(bio_out, "[ unavailable ]\n");
512: if(test_avail_noise)
513: ERR_print_errors_fp(stdout);
514: ERR_clear_error();
515: }
516: }
517: if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
518: goto end;
519: ENGINE_free(e);
520: }
521: else
522: ERR_print_errors(bio_err);
523: }
524:
525: ret=0;
526: end:
527:
528: ERR_print_errors(bio_err);
529: sk_pop_free(engines, identity);
530: sk_pop_free(pre_cmds, identity);
531: sk_pop_free(post_cmds, identity);
532: if (bio_out != NULL) BIO_free_all(bio_out);
533: apps_shutdown();
534: OPENSSL_EXIT(ret);
535: }
536: #else
537:
538: # if PEDANTIC
539: static void *dummy=&dummy;
540: # endif
541:
542: #endif