X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fstoreutl.c;h=bc212c6b7c74a6ad353b6067a89351fdadad7d83;hp=55a11e594d1f214f4dad137b64c36a1c65b44bd3;hb=db42bb440e76399b89fc8ae04644441a2a5f6821;hpb=dab2cd68e7cc304c9b1a4e7cee18a98711771a53 diff --git a/apps/storeutl.c b/apps/storeutl.c index 55a11e594d..bc212c6b7c 100644 --- a/apps/storeutl.c +++ b/apps/storeutl.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -14,13 +14,20 @@ #include #include #include +#include /* s2i_ASN1_INTEGER */ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, - int text, int noout, int recursive, int indent, BIO *out); + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog); typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN, - OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE + OPT_NOOUT, OPT_TEXT, OPT_RECURSIVE, + OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS, + OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL, + OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS, + OPT_MD } OPTION_CHOICE; const OPTIONS storeutl_options[] = { @@ -30,6 +37,15 @@ const OPTIONS storeutl_options[] = { {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"text", OPT_TEXT, '-', "Print a text form of the objects"}, {"noout", OPT_NOOUT, '-', "No PEM output, just status"}, + {"certs", OPT_SEARCHFOR_CERTS, '-', "Search for certificates only"}, + {"keys", OPT_SEARCHFOR_KEYS, '-', "Search for keys only"}, + {"crls", OPT_SEARCHFOR_CRLS, '-', "Search for CRLs only"}, + {"subject", OPT_CRITERION_SUBJECT, 's', "Search by subject"}, + {"issuer", OPT_CRITERION_ISSUER, 's', "Search by issuer and serial, issuer name"}, + {"serial", OPT_CRITERION_SERIAL, 's', "Search by issuer and serial, serial number"}, + {"fingerprint", OPT_CRITERION_FINGERPRINT, 's', "Search by public key fingerprint, given in hex"}, + {"alias", OPT_CRITERION_ALIAS, 's', "Search by alias"}, + {"", OPT_MD, '-', "Any supported digest"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif @@ -46,6 +62,15 @@ int storeutl_main(int argc, char *argv[]) OPTION_CHOICE o; char *prog = opt_init(argc, argv, storeutl_options); PW_CB_DATA pw_cb_data; + int expected = 0; + int criterion = 0; + X509_NAME *subject = NULL, *issuer = NULL; + ASN1_INTEGER *serial = NULL; + unsigned char *fingerprint = NULL; + size_t fingerprintlen = 0; + char *alias = NULL; + OSSL_STORE_SEARCH *search = NULL; + const EVP_MD *digest = NULL; while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -73,9 +98,147 @@ int storeutl_main(int argc, char *argv[]) case OPT_RECURSIVE: recursive = 1; break; + case OPT_SEARCHFOR_CERTS: + case OPT_SEARCHFOR_KEYS: + case OPT_SEARCHFOR_CRLS: + if (expected != 0) { + BIO_printf(bio_err, "%s: only one search type can be given.\n", + prog); + goto end; + } + { + static const struct { + enum OPTION_choice choice; + int type; + } map[] = { + {OPT_SEARCHFOR_CERTS, OSSL_STORE_INFO_CERT}, + {OPT_SEARCHFOR_KEYS, OSSL_STORE_INFO_PKEY}, + {OPT_SEARCHFOR_CRLS, OSSL_STORE_INFO_CRL}, + }; + size_t i; + + for (i = 0; i < OSSL_NELEM(map); i++) { + if (o == map[i].choice) { + expected = map[i].type; + break; + } + } + /* + * If expected wasn't set at this point, it means the map + * isn't syncronised with the possible options leading here. + */ + OPENSSL_assert(expected != 0); + } + break; + case OPT_CRITERION_SUBJECT: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_NAME; + if (subject != NULL) { + BIO_printf(bio_err, "%s: subject already given.\n", + prog); + goto end; + } + if ((subject = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse subject argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_ISSUER: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && issuer != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (issuer != NULL) { + BIO_printf(bio_err, "%s: issuer already given.\n", + prog); + goto end; + } + if ((issuer = parse_name(opt_arg(), MBSTRING_UTF8, 1)) == NULL) { + BIO_printf(bio_err, "%s: can't parse issuer argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_SERIAL: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_ISSUER_SERIAL + && serial != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + if (serial != NULL) { + BIO_printf(bio_err, "%s: serial number already given.\n", + prog); + goto end; + } + if ((serial = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse serial number argument.\n", + prog); + goto end; + } + break; + case OPT_CRITERION_FINGERPRINT: + if (criterion != 0 + || (criterion == OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT + && fingerprint != NULL)) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; + if (fingerprint != NULL) { + BIO_printf(bio_err, "%s: fingerprint already given.\n", + prog); + goto end; + } + { + long tmplen = 0; + + if ((fingerprint = OPENSSL_hexstr2buf(opt_arg(), &tmplen)) + == NULL) { + BIO_printf(bio_err, + "%s: can't parse fingerprint argument.\n", + prog); + goto end; + } + fingerprintlen = (size_t)tmplen; + } + break; + case OPT_CRITERION_ALIAS: + if (criterion != 0) { + BIO_printf(bio_err, "%s: criterion already given.\n", + prog); + goto end; + } + criterion = OSSL_STORE_SEARCH_BY_ALIAS; + if (alias != NULL) { + BIO_printf(bio_err, "%s: alias already given.\n", + prog); + goto end; + } + if ((alias = OPENSSL_strdup(opt_arg())) == NULL) { + BIO_printf(bio_err, "%s: can't parse alias argument.\n", + prog); + goto end; + } + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; + case OPT_MD: + if (!opt_md(opt_unknown(), &digest)) + goto opthelp; } } argc = opt_num_rest(); @@ -90,6 +253,45 @@ int storeutl_main(int argc, char *argv[]) goto opthelp; } + if (criterion != 0) { + switch (criterion) { + case OSSL_STORE_SEARCH_BY_NAME: + if ((search = OSSL_STORE_SEARCH_by_name(subject)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL: + if (issuer == NULL || serial == NULL) { + BIO_printf(bio_err, + "%s: both -issuer and -serial must be given.\n", + prog); + goto end; + } + if ((search = OSSL_STORE_SEARCH_by_issuer_serial(issuer, serial)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT: + if ((search = OSSL_STORE_SEARCH_by_key_fingerprint(digest, + fingerprint, + fingerprintlen)) + == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + case OSSL_STORE_SEARCH_BY_ALIAS: + if ((search = OSSL_STORE_SEARCH_by_alias(alias)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + break; + } + } + if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; @@ -101,10 +303,17 @@ int storeutl_main(int argc, char *argv[]) if (out == NULL) goto end; - ret = process(argv[0], get_ui_method(), &pw_cb_data, text, noout, recursive, - 0, out); + ret = process(argv[0], get_ui_method(), &pw_cb_data, + expected, criterion, search, + text, noout, recursive, 0, out, prog); end: + OPENSSL_free(fingerprint); + OPENSSL_free(alias); + ASN1_INTEGER_free(serial); + X509_NAME_free(subject); + X509_NAME_free(issuer); + OSSL_STORE_SEARCH_free(search); BIO_free_all(out); OPENSSL_free(passin); release_engine(e); @@ -125,7 +334,9 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...) } static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, - int text, int noout, int recursive, int indent, BIO *out) + int expected, int criterion, OSSL_STORE_SEARCH *search, + int text, int noout, int recursive, int indent, BIO *out, + const char *prog) { OSSL_STORE_CTX *store_ctx = NULL; int ret = 1, items = 0; @@ -137,6 +348,27 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, return ret; } + if (expected != 0) { + if (!OSSL_STORE_expect(store_ctx, expected)) { + ERR_print_errors(bio_err); + goto end2; + } + } + + if (criterion != 0) { + if (!OSSL_STORE_supports_search(store_ctx, criterion)) { + BIO_printf(bio_err, + "%s: the store scheme doesn't support the given search criteria.\n", + prog); + goto end2; + } + + if (!OSSL_STORE_find(store_ctx, search)) { + ERR_print_errors(bio_err); + goto end2; + } + } + /* From here on, we count errors, and we'll return the count at the end */ ret = 0; @@ -188,8 +420,9 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, case OSSL_STORE_INFO_NAME: if (recursive) { const char *suburi = OSSL_STORE_INFO_get0_NAME(info); - ret += process(suburi, uimeth, uidata, text, noout, recursive, - indent + 2, out); + ret += process(suburi, uimeth, uidata, + expected, criterion, search, + text, noout, recursive, indent + 2, out, prog); } break; case OSSL_STORE_INFO_PARAMS: @@ -230,6 +463,7 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, } indent_printf(indent, out, "Total found: %d\n", items); + end2: if (!OSSL_STORE_close(store_ctx)) { ERR_print_errors(bio_err); ret++;