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