X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fstore%2Fstore_lib.c;h=1c43547666f1b7a487761a23a4ffcb4347b48cc1;hb=3e0076c213ec2d1149a9a89f9bc141d1a1a44630;hp=d5bb8b88ce4cde7c9534dc6f0c3fd706053d3efc;hpb=4c17819c41b32f6652662d4a2942e35c67d7d650;p=oweals%2Fopenssl.git diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index d5bb8b88ce..1c43547666 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -1,5 +1,5 @@ /* - * 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 * this file except in compliance with the License. You can obtain a copy @@ -7,8 +7,12 @@ * https://www.openssl.org/source/license.html */ +#include "e_os.h" #include #include +#include + +#include "e_os.h" #include #include @@ -24,6 +28,10 @@ struct ossl_store_ctx_st { void *ui_data; OSSL_STORE_post_process_info_fn post_process; void *post_process_data; + int expected_type; + + /* 0 before the first STORE_load(), 1 otherwise */ + int loading; }; OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, @@ -31,36 +39,70 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, OSSL_STORE_post_process_info_fn post_process, void *post_process_data) { - const OSSL_STORE_LOADER *loader; + const OSSL_STORE_LOADER *loader = NULL; OSSL_STORE_LOADER_CTX *loader_ctx = NULL; OSSL_STORE_CTX *ctx = NULL; - char scheme_copy[256], *p; - + char scheme_copy[256], *p, *schemes[2]; + size_t schemes_n = 0; + size_t i; + + /* + * Put the file scheme first. If the uri does represent an existing file, + * possible device name and all, then it should be loaded. Only a failed + * attempt at loading a local file should have us try something else. + */ + schemes[schemes_n++] = "file"; + + /* + * Now, check if we have something that looks like a scheme, and add it + * as a second scheme. However, also check if there's an authority start + * (://), because that will invalidate the previous file scheme. Also, + * check that this isn't actually the file scheme, as there's no point + * going through that one twice! + */ OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy)); if ((p = strchr(scheme_copy, ':')) != NULL) { - *p = '\0'; - p = scheme_copy; - } else { - p = "file"; + *p++ = '\0'; + if (strcasecmp(scheme_copy, "file") != 0) { + if (strncmp(p, "//", 2) == 0) + schemes_n--; /* Invalidate the file scheme */ + schemes[schemes_n++] = scheme_copy; + } } - if ((loader = ossl_store_get0_loader_int(p)) == NULL - || (loader_ctx = loader->open(loader, uri, ui_method, ui_data)) == NULL) - goto done; + ERR_set_mark(); + + /* Try each scheme until we find one that could open the URI */ + for (i = 0; loader_ctx == NULL && i < schemes_n; i++) { + if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) + loader_ctx = loader->open(loader, uri, ui_method, ui_data); + } + if (loader_ctx == NULL) + goto err; + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE); - goto done; + goto err; } ctx->loader = loader; ctx->loader_ctx = loader_ctx; - loader_ctx = NULL; ctx->ui_method = ui_method; ctx->ui_data = ui_data; ctx->post_process = post_process; ctx->post_process_data = post_process_data; - done: + /* + * If the attempt to open with the 'file' scheme loader failed and the + * other scheme loader succeeded, the failure to open with the 'file' + * scheme loader leaves an error on the error stack. Let's remove it. + */ + ERR_pop_to_mark(); + + return ctx; + + err: + ERR_clear_last_mark(); if (loader_ctx != NULL) { /* * We ignore a returned error because we will return NULL anyway in @@ -69,27 +111,67 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method, */ (void)loader->close(loader_ctx); } - return ctx; + return NULL; } int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...) { va_list args; - int ret = 0; + int ret; va_start(args, cmd); - if (ctx->loader->ctrl != NULL) - ret = ctx->loader->ctrl(ctx->loader_ctx, cmd, args); + ret = OSSL_STORE_vctrl(ctx, cmd, args); va_end(args); return ret; } +int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args) +{ + if (ctx->loader->ctrl != NULL) + return ctx->loader->ctrl(ctx->loader_ctx, cmd, args); + return 0; +} + +int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type) +{ + if (ctx->loading) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_EXPECT, + OSSL_STORE_R_LOADING_STARTED); + return 0; + } + + ctx->expected_type = expected_type; + if (ctx->loader->expect != NULL) + return ctx->loader->expect(ctx->loader_ctx, expected_type); + return 1; +} + +int OSSL_STORE_find(OSSL_STORE_CTX *ctx, OSSL_STORE_SEARCH *search) +{ + if (ctx->loading) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND, + OSSL_STORE_R_LOADING_STARTED); + return 0; + } + if (ctx->loader->find == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_FIND, + OSSL_STORE_R_UNSUPPORTED_OPERATION); + return 0; + } + + return ctx->loader->find(ctx->loader_ctx, search); +} + OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx) { OSSL_STORE_INFO *v = NULL; + ctx->loading = 1; again: + if (OSSL_STORE_eof(ctx)) + return NULL; + v = ctx->loader->load(ctx->loader_ctx, ctx->ui_method, ctx->ui_data); if (ctx->post_process != NULL && v != NULL) { @@ -103,6 +185,24 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx) goto again; } + if (v != NULL && ctx->expected_type != 0) { + int returned_type = OSSL_STORE_INFO_get_type(v); + + if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) { + /* + * Soft assert here so those who want to harsly weed out faulty + * loaders can do so using a debugging version of libcrypto. + */ + if (ctx->loader->expect != NULL) + assert(ctx->expected_type == returned_type); + + if (ctx->expected_type != returned_type) { + OSSL_STORE_INFO_free(v); + goto again; + } + } + } + return v; } @@ -126,8 +226,7 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx) /* * Functions to generate OSSL_STORE_INFOs, one function for each type we - * support having in them. Along with each of them, one macro that - * can be used to determine what types are supported. + * support having in them as well as a generic constructor. * * In all cases, ownership of the object is transfered to the OSSL_STORE_INFO * and will therefore be freed when the OSSL_STORE_INFO is freed. @@ -369,6 +468,135 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info) } } +int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type) +{ + OSSL_STORE_SEARCH tmp_search; + + if (ctx->loader->find == NULL) + return 0; + tmp_search.search_type = search_type; + return ctx->loader->find(NULL, &tmp_search); +} + +/* Search term constructors */ +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_NAME, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_NAME; + search->name = name; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, + const ASN1_INTEGER *serial) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ISSUER_SERIAL, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; + search->name = name; + search->serial = serial; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest, + const unsigned char + *bytes, size_t len) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (digest != NULL && len != (size_t)EVP_MD_size(digest)) { + char buf1[20], buf2[20]; + + BIO_snprintf(buf1, sizeof(buf1), "%d", EVP_MD_size(digest)); + BIO_snprintf(buf2, sizeof(buf2), "%zu", len); + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT, + OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST); + ERR_add_error_data(5, EVP_MD_name(digest), " size is ", buf1, + ", fingerprint size is ", buf2); + } + + search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT; + search->digest = digest; + search->string = bytes; + search->stringlength = len; + return search; +} + +OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias) +{ + OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + + if (search == NULL) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_SEARCH_BY_ALIAS, + ERR_R_MALLOC_FAILURE); + return NULL; + } + + search->search_type = OSSL_STORE_SEARCH_BY_ALIAS; + search->string = (const unsigned char *)alias; + search->stringlength = strlen(alias); + return search; +} + +/* Search term destructor */ +void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search) +{ + OPENSSL_free(search); +} + +/* Search term accessors */ +int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion) +{ + return criterion->search_type; +} + +X509_NAME *OSSL_STORE_SEARCH_get0_name(OSSL_STORE_SEARCH *criterion) +{ + return criterion->name; +} + +const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH + *criterion) +{ + return criterion->serial; +} + +const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH + *criterion, size_t *length) +{ + *length = criterion->stringlength; + return criterion->string; +} + +const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion) +{ + return (const char *)criterion->string; +} + +const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion) +{ + return criterion->digest; +} + /* Internal functions */ OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name, BUF_MEM *embedded)