Move the code for 'openssl list' to its own translation unit.
[openssl.git] / apps / list.c
1 /*
2  * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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 <string.h>
11 #include <openssl/evp.h>
12 #include <openssl/err.h>
13 #include "apps.h"
14 #include "progs.h"
15 #include "opt.h"
16
17 static void list_cipher_fn(const EVP_CIPHER *c,
18                            const char *from, const char *to, void *arg)
19 {
20     if (c != NULL) {
21         BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
22     } else {
23         if (from == NULL)
24             from = "<undefined>";
25         if (to == NULL)
26             to = "<undefined>";
27         BIO_printf(arg, "%s => %s\n", from, to);
28     }
29 }
30
31 static void list_md_fn(const EVP_MD *m,
32                        const char *from, const char *to, void *arg)
33 {
34     if (m != NULL) {
35         BIO_printf(arg, "%s\n", EVP_MD_name(m));
36     } else {
37         if (from == NULL)
38             from = "<undefined>";
39         if (to == NULL)
40             to = "<undefined>";
41         BIO_printf((BIO *)arg, "%s => %s\n", from, to);
42     }
43 }
44
45 static void list_mac_fn(const EVP_MAC *m,
46                         const char *from, const char *to, void *arg)
47 {
48     if (m != NULL) {
49         BIO_printf(arg, "%s\n", EVP_MAC_name(m));
50     } else {
51         if (from == NULL)
52             from = "<undefined>";
53         if (to == NULL)
54             to = "<undefined>";
55         BIO_printf(arg, "%s => %s\n", from, to);
56     }
57 }
58
59 static void list_missing_help(void)
60 {
61     const FUNCTION *fp;
62     const OPTIONS *o;
63
64     for (fp = functions; fp->name != NULL; fp++) {
65         if ((o = fp->help) != NULL) {
66             /* If there is help, list what flags are not documented. */
67             for ( ; o->name != NULL; o++) {
68                 if (o->helpstr == NULL)
69                     BIO_printf(bio_out, "%s %s\n", fp->name, o->name);
70             }
71         } else if (fp->func != dgst_main) {
72             /* If not aliased to the dgst command, */
73             BIO_printf(bio_out, "%s *\n", fp->name);
74         }
75     }
76 }
77
78 static void list_objects(void)
79 {
80     int max_nid = OBJ_new_nid(0);
81     int i;
82     char *oid_buf = NULL;
83     int oid_size = 0;
84
85     /* Skip 0, since that's NID_undef */
86     for (i = 1; i < max_nid; i++) {
87         const ASN1_OBJECT *obj = OBJ_nid2obj(i);
88         const char *sn = OBJ_nid2sn(i);
89         const char *ln = OBJ_nid2ln(i);
90         int n = 0;
91
92         /*
93          * If one of the retrieved objects somehow generated an error,
94          * we ignore it.  The check for NID_undef below will detect the
95          * error and simply skip to the next NID.
96          */
97         ERR_clear_error();
98
99         if (OBJ_obj2nid(obj) == NID_undef)
100             continue;
101
102         if ((n = OBJ_obj2txt(NULL, 0, obj, 1)) == 0) {
103             BIO_printf(bio_out, "# None-OID object: %s, %s\n", sn, ln);
104             continue;
105         }
106         if (n < 0)
107             break;               /* Error */
108
109         if (n > oid_size) {
110             oid_buf = OPENSSL_realloc(oid_buf, n + 1);
111             if (oid_buf == NULL) {
112                 BIO_printf(bio_err, "ERROR: Memory allocation\n");
113                 break;           /* Error */
114             }
115             oid_size = n + 1;
116         }
117         if (OBJ_obj2txt(oid_buf, oid_size, obj, 1) < 0)
118             break;               /* Error */
119         if (ln == NULL || strcmp(sn, ln) == 0)
120             BIO_printf(bio_out, "%s = %s\n", sn, oid_buf);
121         else
122             BIO_printf(bio_out, "%s = %s, %s\n", sn, ln, oid_buf);
123     }
124
125     OPENSSL_free(oid_buf);
126 }
127
128 static void list_options_for_command(const char *command)
129 {
130     const FUNCTION *fp;
131     const OPTIONS *o;
132
133     for (fp = functions; fp->name != NULL; fp++)
134         if (strcmp(fp->name, command) == 0)
135             break;
136     if (fp->name == NULL) {
137         BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n",
138                 command);
139         return;
140     }
141
142     if ((o = fp->help) == NULL)
143         return;
144
145     for ( ; o->name != NULL; o++) {
146         if (o->name == OPT_HELP_STR
147                 || o->name == OPT_MORE_STR
148                 || o->name[0] == '\0')
149             continue;
150         BIO_printf(bio_out, "%s %c\n", o->name, o->valtype);
151     }
152 }
153
154 static void list_type(FUNC_TYPE ft, int one)
155 {
156     FUNCTION *fp;
157     int i = 0;
158     DISPLAY_COLUMNS dc;
159
160     memset(&dc, 0, sizeof(dc));
161     if (!one)
162         calculate_columns(functions, &dc);
163
164     for (fp = functions; fp->name != NULL; fp++) {
165         if (fp->type != ft)
166             continue;
167         if (one) {
168             BIO_printf(bio_out, "%s\n", fp->name);
169         } else {
170             if (i % dc.columns == 0 && i > 0)
171                 BIO_printf(bio_out, "\n");
172             BIO_printf(bio_out, "%-*s", dc.width, fp->name);
173             i++;
174         }
175     }
176     if (!one)
177         BIO_printf(bio_out, "\n\n");
178 }
179
180 static void list_pkey(void)
181 {
182     int i;
183
184     for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
185         const EVP_PKEY_ASN1_METHOD *ameth;
186         int pkey_id, pkey_base_id, pkey_flags;
187         const char *pinfo, *pem_str;
188         ameth = EVP_PKEY_asn1_get0(i);
189         EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
190                                 &pinfo, &pem_str, ameth);
191         if (pkey_flags & ASN1_PKEY_ALIAS) {
192             BIO_printf(bio_out, "Name: %s\n", OBJ_nid2ln(pkey_id));
193             BIO_printf(bio_out, "\tAlias for: %s\n",
194                        OBJ_nid2ln(pkey_base_id));
195         } else {
196             BIO_printf(bio_out, "Name: %s\n", pinfo);
197             BIO_printf(bio_out, "\tType: %s Algorithm\n",
198                        pkey_flags & ASN1_PKEY_DYNAMIC ?
199                        "External" : "Builtin");
200             BIO_printf(bio_out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
201             if (pem_str == NULL)
202                 pem_str = "(none)";
203             BIO_printf(bio_out, "\tPEM string: %s\n", pem_str);
204         }
205
206     }
207 }
208
209 static void list_pkey_meth(void)
210 {
211     size_t i;
212     size_t meth_count = EVP_PKEY_meth_get_count();
213
214     for (i = 0; i < meth_count; i++) {
215         const EVP_PKEY_METHOD *pmeth = EVP_PKEY_meth_get0(i);
216         int pkey_id, pkey_flags;
217
218         EVP_PKEY_meth_get0_info(&pkey_id, &pkey_flags, pmeth);
219         BIO_printf(bio_out, "%s\n", OBJ_nid2ln(pkey_id));
220         BIO_printf(bio_out, "\tType: %s Algorithm\n",
221                    pkey_flags & ASN1_PKEY_DYNAMIC ?  "External" : "Builtin");
222     }
223 }
224
225 static void list_engines(void)
226 {
227 #ifndef OPENSSL_NO_ENGINE
228     ENGINE *e;
229
230     BIO_puts(bio_out, "Engines:\n");
231     e = ENGINE_get_first();
232     while (e) {
233         BIO_printf(bio_out, "%s\n", ENGINE_get_id(e));
234         e = ENGINE_get_next(e);
235     }
236 #else
237     BIO_puts(bio_out, "Engine support is disabled.\n");
238 #endif
239 }
240
241 static void list_disabled(void)
242 {
243     BIO_puts(bio_out, "Disabled algorithms:\n");
244 #ifdef OPENSSL_NO_ARIA
245     BIO_puts(bio_out, "ARIA\n");
246 #endif
247 #ifdef OPENSSL_NO_BF
248     BIO_puts(bio_out, "BF\n");
249 #endif
250 #ifdef OPENSSL_NO_BLAKE2
251     BIO_puts(bio_out, "BLAKE2\n");
252 #endif
253 #ifdef OPENSSL_NO_CAMELLIA
254     BIO_puts(bio_out, "CAMELLIA\n");
255 #endif
256 #ifdef OPENSSL_NO_CAST
257     BIO_puts(bio_out, "CAST\n");
258 #endif
259 #ifdef OPENSSL_NO_CMAC
260     BIO_puts(bio_out, "CMAC\n");
261 #endif
262 #ifdef OPENSSL_NO_CMS
263     BIO_puts(bio_out, "CMS\n");
264 #endif
265 #ifdef OPENSSL_NO_COMP
266     BIO_puts(bio_out, "COMP\n");
267 #endif
268 #ifdef OPENSSL_NO_DES
269     BIO_puts(bio_out, "DES\n");
270 #endif
271 #ifdef OPENSSL_NO_DGRAM
272     BIO_puts(bio_out, "DGRAM\n");
273 #endif
274 #ifdef OPENSSL_NO_DH
275     BIO_puts(bio_out, "DH\n");
276 #endif
277 #ifdef OPENSSL_NO_DSA
278     BIO_puts(bio_out, "DSA\n");
279 #endif
280 #if defined(OPENSSL_NO_DTLS)
281     BIO_puts(bio_out, "DTLS\n");
282 #endif
283 #if defined(OPENSSL_NO_DTLS1)
284     BIO_puts(bio_out, "DTLS1\n");
285 #endif
286 #if defined(OPENSSL_NO_DTLS1_2)
287     BIO_puts(bio_out, "DTLS1_2\n");
288 #endif
289 #ifdef OPENSSL_NO_EC
290     BIO_puts(bio_out, "EC\n");
291 #endif
292 #ifdef OPENSSL_NO_EC2M
293     BIO_puts(bio_out, "EC2M\n");
294 #endif
295 #ifdef OPENSSL_NO_ENGINE
296     BIO_puts(bio_out, "ENGINE\n");
297 #endif
298 #ifdef OPENSSL_NO_GOST
299     BIO_puts(bio_out, "GOST\n");
300 #endif
301 #ifdef OPENSSL_NO_IDEA
302     BIO_puts(bio_out, "IDEA\n");
303 #endif
304 #ifdef OPENSSL_NO_MD2
305     BIO_puts(bio_out, "MD2\n");
306 #endif
307 #ifdef OPENSSL_NO_MD4
308     BIO_puts(bio_out, "MD4\n");
309 #endif
310 #ifdef OPENSSL_NO_MD5
311     BIO_puts(bio_out, "MD5\n");
312 #endif
313 #ifdef OPENSSL_NO_MDC2
314     BIO_puts(bio_out, "MDC2\n");
315 #endif
316 #ifdef OPENSSL_NO_OCB
317     BIO_puts(bio_out, "OCB\n");
318 #endif
319 #ifdef OPENSSL_NO_OCSP
320     BIO_puts(bio_out, "OCSP\n");
321 #endif
322 #ifdef OPENSSL_NO_PSK
323     BIO_puts(bio_out, "PSK\n");
324 #endif
325 #ifdef OPENSSL_NO_RC2
326     BIO_puts(bio_out, "RC2\n");
327 #endif
328 #ifdef OPENSSL_NO_RC4
329     BIO_puts(bio_out, "RC4\n");
330 #endif
331 #ifdef OPENSSL_NO_RC5
332     BIO_puts(bio_out, "RC5\n");
333 #endif
334 #ifdef OPENSSL_NO_RMD160
335     BIO_puts(bio_out, "RMD160\n");
336 #endif
337 #ifdef OPENSSL_NO_RSA
338     BIO_puts(bio_out, "RSA\n");
339 #endif
340 #ifdef OPENSSL_NO_SCRYPT
341     BIO_puts(bio_out, "SCRYPT\n");
342 #endif
343 #ifdef OPENSSL_NO_SCTP
344     BIO_puts(bio_out, "SCTP\n");
345 #endif
346 #ifdef OPENSSL_NO_SEED
347     BIO_puts(bio_out, "SEED\n");
348 #endif
349 #ifdef OPENSSL_NO_SM2
350     BIO_puts(bio_out, "SM2\n");
351 #endif
352 #ifdef OPENSSL_NO_SM3
353     BIO_puts(bio_out, "SM3\n");
354 #endif
355 #ifdef OPENSSL_NO_SM4
356     BIO_puts(bio_out, "SM4\n");
357 #endif
358 #ifdef OPENSSL_NO_SOCK
359     BIO_puts(bio_out, "SOCK\n");
360 #endif
361 #ifdef OPENSSL_NO_SRP
362     BIO_puts(bio_out, "SRP\n");
363 #endif
364 #ifdef OPENSSL_NO_SRTP
365     BIO_puts(bio_out, "SRTP\n");
366 #endif
367 #ifdef OPENSSL_NO_SSL3
368     BIO_puts(bio_out, "SSL3\n");
369 #endif
370 #ifdef OPENSSL_NO_TLS1
371     BIO_puts(bio_out, "TLS1\n");
372 #endif
373 #ifdef OPENSSL_NO_TLS1_1
374     BIO_puts(bio_out, "TLS1_1\n");
375 #endif
376 #ifdef OPENSSL_NO_TLS1_2
377     BIO_puts(bio_out, "TLS1_2\n");
378 #endif
379 #ifdef OPENSSL_NO_WHIRLPOOL
380     BIO_puts(bio_out, "WHIRLPOOL\n");
381 #endif
382 #ifndef ZLIB
383     BIO_puts(bio_out, "ZLIB\n");
384 #endif
385 }
386
387 /* Unified enum for help and list commands. */
388 typedef enum HELPLIST_CHOICE {
389     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ONE,
390     OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS,
391     OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
392     OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_ENGINES, OPT_DISABLED,
393     OPT_MISSING_HELP, OPT_OBJECTS
394 } HELPLIST_CHOICE;
395
396 const OPTIONS list_options[] = {
397     {"help", OPT_HELP, '-', "Display this summary"},
398     {"1", OPT_ONE, '-', "List in one column"},
399     {"commands", OPT_COMMANDS, '-', "List of standard commands"},
400     {"digest-commands", OPT_DIGEST_COMMANDS, '-',
401      "List of message digest commands"},
402     {"digest-algorithms", OPT_DIGEST_ALGORITHMS, '-',
403      "List of message digest algorithms"},
404     {"mac-algorithms", OPT_MAC_ALGORITHMS, '-',
405      "List of message authentication code algorithms"},
406     {"cipher-commands", OPT_CIPHER_COMMANDS, '-', "List of cipher commands"},
407     {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-',
408      "List of cipher algorithms"},
409     {"public-key-algorithms", OPT_PK_ALGORITHMS, '-',
410      "List of public key algorithms"},
411     {"public-key-methods", OPT_PK_METHOD, '-',
412      "List of public key methods"},
413     {"engines", OPT_ENGINES, '-',
414      "List of loaded engines"},
415     {"disabled", OPT_DISABLED, '-',
416      "List of disabled features"},
417     {"missing-help", OPT_MISSING_HELP, '-',
418      "List missing detailed help strings"},
419     {"options", OPT_OPTIONS, 's',
420      "List options for specified command"},
421     {"objects", OPT_OBJECTS, '-',
422      "List built in objects (OID<->name mappings)"},
423     {NULL}
424 };
425
426 int list_main(int argc, char **argv)
427 {
428     char *prog;
429     HELPLIST_CHOICE o;
430     int one = 0, done = 0;
431
432     prog = opt_init(argc, argv, list_options);
433     while ((o = opt_next()) != OPT_EOF) {
434         switch (o) {
435         case OPT_EOF:  /* Never hit, but suppresses warning */
436         case OPT_ERR:
437 opthelp:
438             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
439             return 1;
440         case OPT_HELP:
441             opt_help(list_options);
442             break;
443         case OPT_ONE:
444             one = 1;
445             break;
446         case OPT_COMMANDS:
447             list_type(FT_general, one);
448             break;
449         case OPT_DIGEST_COMMANDS:
450             list_type(FT_md, one);
451             break;
452         case OPT_DIGEST_ALGORITHMS:
453             EVP_MD_do_all_sorted(list_md_fn, bio_out);
454             break;
455         case OPT_MAC_ALGORITHMS:
456             EVP_MAC_do_all_sorted(list_mac_fn, bio_out);
457             break;
458         case OPT_CIPHER_COMMANDS:
459             list_type(FT_cipher, one);
460             break;
461         case OPT_CIPHER_ALGORITHMS:
462             EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
463             break;
464         case OPT_PK_ALGORITHMS:
465             list_pkey();
466             break;
467         case OPT_PK_METHOD:
468             list_pkey_meth();
469             break;
470         case OPT_ENGINES:
471             list_engines();
472             break;
473         case OPT_DISABLED:
474             list_disabled();
475             break;
476         case OPT_MISSING_HELP:
477             list_missing_help();
478             break;
479         case OPT_OBJECTS:
480             list_objects();
481             break;
482         case OPT_OPTIONS:
483             list_options_for_command(opt_arg());
484             break;
485         }
486         done = 1;
487     }
488     if (opt_num_rest() != 0) {
489         BIO_printf(bio_err, "Extra arguments given.\n");
490         goto opthelp;
491     }
492
493     if (!done)
494         goto opthelp;
495
496     return 0;
497 }