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