source: rtems-libbsd/freebsd/crypto/openssl/apps/storeutl.c @ 0fecf49

5
Last change on this file since 0fecf49 was 0fecf49, checked in by Christian Mauderer <christian.mauderer@…>, on 03/26/19 at 09:19:22

bin/openssl: Import from FreeBSD.

  • Property mode set to 100644
File size: 16.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
5 *
6 * Licensed under the OpenSSL license (the "License").  You may not use
7 * this file except in compliance with the License.  You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12#include <openssl/opensslconf.h>
13
14#include "apps.h"
15#include "progs.h"
16#include <openssl/err.h>
17#include <openssl/pem.h>
18#include <openssl/store.h>
19#include <openssl/x509v3.h>      /* s2i_ASN1_INTEGER */
20
21static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
22                   int expected, int criterion, OSSL_STORE_SEARCH *search,
23                   int text, int noout, int recursive, int indent, BIO *out,
24                   const char *prog);
25
26typedef enum OPTION_choice {
27    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
28    OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE,
29    OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
30    OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
31    OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
32    OPT_MD
33} OPTION_CHOICE;
34
35const OPTIONS storeutl_options[] = {
36    {OPT_HELP_STR, 1, '-', "Usage: %s [options] uri\nValid options are:\n"},
37    {"help", OPT_HELP, '-', "Display this summary"},
38    {"out", OPT_OUT, '>', "Output file - default stdout"},
39    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
40    {"text", OPT_TEXT, '-', "Print a text form of the objects"},
41    {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
42    {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"},
43    {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"},
44    {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"},
45    {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"},
46    {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"},
47    {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"},
48    {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"},
49    {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"},
50    {"", OPT_MD, '-', "Any supported digest"},
51#ifndef OPENSSL_NO_ENGINE
52    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
53#endif
54    {"r", OPT_RECURSIVE, '-', "Recurse through names"},
55    {NULL}
56};
57
58int storeutl_main(int argc, char *argv[])
59{
60    int ret = 1, noout = 0, text = 0, recursive = 0;
61    char *outfile = NULL, *passin = NULL, *passinarg = NULL;
62    BIO *out = NULL;
63    ENGINE *e = NULL;
64    OPTION_CHOICE o;
65    char *prog = opt_init(argc, argv, storeutl_options);
66    PW_CB_DATA pw_cb_data;
67    int expected = 0;
68    int criterion = 0;
69    X509_NAME *subject = NULL, *issuer = NULL;
70    ASN1_INTEGER *serial = NULL;
71    unsigned char *fingerprint = NULL;
72    size_t fingerprintlen = 0;
73    char *alias = NULL;
74    OSSL_STORE_SEARCH *search = NULL;
75    const EVP_MD *digest = NULL;
76
77    while ((o = opt_next()) != OPT_EOF) {
78        switch (o) {
79        case OPT_EOF:
80        case OPT_ERR:
81 opthelp:
82            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
83            goto end;
84        case OPT_HELP:
85            opt_help(storeutl_options);
86            ret = 0;
87            goto end;
88        case OPT_OUT:
89            outfile = opt_arg();
90            break;
91        case OPT_PASSIN:
92            passinarg = opt_arg();
93            break;
94        case OPT_NOOUT:
95            noout = 1;
96            break;
97        case OPT_TEXT:
98            text = 1;
99            break;
100        case OPT_RECURSIVE:
101            recursive = 1;
102            break;
103        case OPT_SEARCHFOR_CERTS:
104        case OPT_SEARCHFOR_KEYS:
105        case OPT_SEARCHFOR_CRLS:
106            if (expected != 0) {
107                BIO_printf(bio_err, "%s: only one search type can be given.\n",
108                           prog);
109                goto end;
110            }
111            {
112                static const struct {
113                    enum OPTION_choice choice;
114                    int type;
115                } map[] = {
116                    {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT},
117                    {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY},
118                    {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL},
119                };
120                size_t i;
121
122                for (i = 0; i < OSSL_NELEM(map); i++) {
123                    if (o == map[i].choice) {
124                        expected = map[i].type;
125                        break;
126                    }
127                }
128                /*
129                 * If expected wasn't set at this point, it means the map
130                 * isn't syncronised with the possible options leading here.
131                 */
132                OPENSSL_assert(expected != 0);
133            }
134            break;
135        case OPT_CRITERION_SUBJECT:
136            if (criterion != 0) {
137                BIO_printf(bio_err, "%s: criterion already given.\n",
138                           prog);
139                goto end;
140            }
141            criterion = OSSL_STORE_SEARCH_BY_NAME;
142            if (subject != NULL) {
143                BIO_printf(bio_err, "%s: subject already given.\n",
144                           prog);
145                goto end;
146            }
147            if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
148                BIO_printf(bio_err, "%s: can't parse subject argument.\n",
149                           prog);
150                goto end;
151            }
152            break;
153        case OPT_CRITERION_ISSUER:
154            if (criterion != 0
155                || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
156                    && issuer != NULL)) {
157                BIO_printf(bio_err, "%s: criterion already given.\n",
158                           prog);
159                goto end;
160            }
161            criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
162            if (issuer != NULL) {
163                BIO_printf(bio_err, "%s: issuer already given.\n",
164                           prog);
165                goto end;
166            }
167            if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) {
168                BIO_printf(bio_err, "%s: can't parse issuer argument.\n",
169                           prog);
170                goto end;
171            }
172            break;
173        case OPT_CRITERION_SERIAL:
174            if (criterion != 0
175                || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL
176                    && serial != NULL)) {
177                BIO_printf(bio_err, "%s: criterion already given.\n",
178                           prog);
179                goto end;
180            }
181            criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
182            if (serial != NULL) {
183                BIO_printf(bio_err, "%s: serial number already given.\n",
184                           prog);
185                goto end;
186            }
187            if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) {
188                BIO_printf(bio_err, "%s: can't parse serial number argument.\n",
189                           prog);
190                goto end;
191            }
192            break;
193        case OPT_CRITERION_FINGERPRINT:
194            if (criterion != 0
195                || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT
196                    && fingerprint != NULL)) {
197                BIO_printf(bio_err, "%s: criterion already given.\n",
198                           prog);
199                goto end;
200            }
201            criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
202            if (fingerprint != NULL) {
203                BIO_printf(bio_err, "%s: fingerprint already given.\n",
204                           prog);
205                goto end;
206            }
207            {
208                long tmplen = 0;
209
210                if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen))
211                    == NULL) {
212                    BIO_printf(bio_err,
213                               "%s: can't parse fingerprint argument.\n",
214                               prog);
215                    goto end;
216                }
217                fingerprintlen = (size_t)tmplen;
218            }
219            break;
220        case OPT_CRITERION_ALIAS:
221            if (criterion != 0) {
222                BIO_printf(bio_err, "%s: criterion already given.\n",
223                           prog);
224                goto end;
225            }
226            criterion = OSSL_STORE_SEARCH_BY_ALIAS;
227            if (alias != NULL) {
228                BIO_printf(bio_err, "%s: alias already given.\n",
229                           prog);
230                goto end;
231            }
232            if ((alias = OPENSSL_strdup(opt_arg())) == NULL) {
233                BIO_printf(bio_err, "%s: can't parse alias argument.\n",
234                           prog);
235                goto end;
236            }
237            break;
238        case OPT_ENGINE:
239            e = setup_engine(opt_arg(), 0);
240            break;
241        case OPT_MD:
242            if (!opt_md(opt_unknown(), &digest))
243                goto opthelp;
244        }
245    }
246    argc = opt_num_rest();
247    argv = opt_rest();
248
249    if (argc == 0) {
250        BIO_printf(bio_err, "%s: No URI given, nothing to do...\n", prog);
251        goto opthelp;
252    }
253    if (argc > 1) {
254        BIO_printf(bio_err, "%s: Unknown extra parameters after URI\n", prog);
255        goto opthelp;
256    }
257
258    if (criterion != 0) {
259        switch (criterion) {
260        case OSSL_STORE_SEARCH_BY_NAME:
261            if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) {
262                ERR_print_errors(bio_err);
263                goto end;
264            }
265            break;
266        case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
267            if (issuer == NULL || serial == NULL) {
268                BIO_printf(bio_err,
269                           "%s: both -issuer and -serial must be given.\n",
270                           prog);
271                goto end;
272            }
273            if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial))
274                == NULL) {
275                ERR_print_errors(bio_err);
276                goto end;
277            }
278            break;
279        case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
280            if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest,
281                                                               fingerprint,
282                                                               fingerprintlen))
283                == NULL) {
284                ERR_print_errors(bio_err);
285                goto end;
286            }
287            break;
288        case OSSL_STORE_SEARCH_BY_ALIAS:
289            if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) {
290                ERR_print_errors(bio_err);
291                goto end;
292            }
293            break;
294        }
295    }
296
297    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
298        BIO_printf(bio_err, "Error getting passwords\n");
299        goto end;
300    }
301    pw_cb_data.password = passin;
302    pw_cb_data.prompt_info = argv[0];
303
304    out = bio_open_default(outfile, 'w', FORMAT_TEXT);
305    if (out == NULL)
306        goto end;
307
308    ret = process(argv[0], get_ui_method(), &pw_cb_data,
309                  expected, criterion, search,
310                  text, noout, recursive, 0, out, prog);
311
312 end:
313    OPENSSL_free(fingerprint);
314    OPENSSL_free(alias);
315    ASN1_INTEGER_free(serial);
316    X509_NAME_free(subject);
317    X509_NAME_free(issuer);
318    OSSL_STORE_SEARCH_free(search);
319    BIO_free_all(out);
320    OPENSSL_free(passin);
321    release_engine(e);
322    return ret;
323}
324
325static int indent_printf(int indent, BIO *bio, const char *format, ...)
326{
327    va_list args;
328    int ret;
329
330    va_start(args, format);
331
332    ret = BIO_printf(bio, "%*s", indent, "") + BIO_vprintf(bio, format, args);
333
334    va_end(args);
335    return ret;
336}
337
338static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
339                   int expected, int criterion, OSSL_STORE_SEARCH *search,
340                   int text, int noout, int recursive, int indent, BIO *out,
341                   const char *prog)
342{
343    OSSL_STORE_CTX *store_ctx = NULL;
344    int ret = 1, items = 0;
345
346    if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL))
347        == NULL) {
348        BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
349        ERR_print_errors(bio_err);
350        return ret;
351    }
352
353    if (expected != 0) {
354        if (!OSSL_STORE_expect(store_ctx, expected)) {
355            ERR_print_errors(bio_err);
356            goto end2;
357        }
358    }
359
360    if (criterion != 0) {
361        if (!OSSL_STORE_supports_search(store_ctx, criterion)) {
362            BIO_printf(bio_err,
363                       "%s: the store scheme doesn't support the given search criteria.\n",
364                       prog);
365            goto end2;
366        }
367
368        if (!OSSL_STORE_find(store_ctx, search)) {
369            ERR_print_errors(bio_err);
370            goto end2;
371        }
372    }
373
374    /* From here on, we count errors, and we'll return the count at the end */
375    ret = 0;
376
377    for (;;) {
378        OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx);
379        int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
380        const char *infostr =
381            info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
382
383        if (info == NULL) {
384            if (OSSL_STORE_eof(store_ctx))
385                break;
386
387            if (OSSL_STORE_error(store_ctx)) {
388                if (recursive)
389                    ERR_clear_error();
390                else
391                    ERR_print_errors(bio_err);
392                ret++;
393                continue;
394            }
395
396            BIO_printf(bio_err,
397                       "ERROR: OSSL_STORE_load() returned NULL without "
398                       "eof or error indications\n");
399            BIO_printf(bio_err, "       This is an error in the loader\n");
400            ERR_print_errors(bio_err);
401            ret++;
402            break;
403        }
404
405        if (type == OSSL_STORE_INFO_NAME) {
406            const char *name = OSSL_STORE_INFO_get0_NAME(info);
407            const char *desc = OSSL_STORE_INFO_get0_NAME_description(info);
408            indent_printf(indent, bio_out, "%d: %s: %s\n", items, infostr,
409                          name);
410            if (desc != NULL)
411                indent_printf(indent, bio_out, "%s\n", desc);
412        } else {
413            indent_printf(indent, bio_out, "%d: %s\n", items, infostr);
414        }
415
416        /*
417         * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in
418         * functionality, so we must figure out how exactly to write things
419         * ourselves...
420         */
421        switch (type) {
422        case OSSL_STORE_INFO_NAME:
423            if (recursive) {
424                const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
425                ret += process(suburi, uimeth, uidata,
426                               expected, criterion, search,
427                               text, noout, recursive, indent + 2, out, prog);
428            }
429            break;
430        case OSSL_STORE_INFO_PARAMS:
431            if (text)
432                EVP_PKEY_print_params(out, OSSL_STORE_INFO_get0_PARAMS(info),
433                                      0, NULL);
434            if (!noout)
435                PEM_write_bio_Parameters(out,
436                                         OSSL_STORE_INFO_get0_PARAMS(info));
437            break;
438        case OSSL_STORE_INFO_PKEY:
439            if (text)
440                EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
441                                       0, NULL);
442            if (!noout)
443                PEM_write_bio_PrivateKey(out, OSSL_STORE_INFO_get0_PKEY(info),
444                                         NULL, NULL, 0, NULL, NULL);
445            break;
446        case OSSL_STORE_INFO_CERT:
447            if (text)
448                X509_print(out, OSSL_STORE_INFO_get0_CERT(info));
449            if (!noout)
450                PEM_write_bio_X509(out, OSSL_STORE_INFO_get0_CERT(info));
451            break;
452        case OSSL_STORE_INFO_CRL:
453            if (text)
454                X509_CRL_print(out, OSSL_STORE_INFO_get0_CRL(info));
455            if (!noout)
456                PEM_write_bio_X509_CRL(out, OSSL_STORE_INFO_get0_CRL(info));
457            break;
458        default:
459            BIO_printf(bio_err, "!!! Unknown code\n");
460            ret++;
461            break;
462        }
463        items++;
464        OSSL_STORE_INFO_free(info);
465    }
466    indent_printf(indent, out, "Total found: %d\n", items);
467
468 end2:
469    if (!OSSL_STORE_close(store_ctx)) {
470        ERR_print_errors(bio_err);
471        ret++;
472    }
473
474    return ret;
475}
Note: See TracBrowser for help on using the repository browser.