1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#if defined (__TANDEM) && defined (_SPT_MODEL_) 11e1051a39Sopenharmony_ci /* 12e1051a39Sopenharmony_ci * These definitions have to come first in SPT due to scoping of the 13e1051a39Sopenharmony_ci * declarations in c99 associated with SPT use of stat. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci# include <sys/types.h> 16e1051a39Sopenharmony_ci# include <sys/stat.h> 17e1051a39Sopenharmony_ci#endif 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci#include "e_os.h" 20e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 21e1051a39Sopenharmony_ci#include <stdio.h> 22e1051a39Sopenharmony_ci#include <time.h> 23e1051a39Sopenharmony_ci#include <errno.h> 24e1051a39Sopenharmony_ci#include <sys/types.h> 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 27e1051a39Sopenharmony_ci# include <sys/stat.h> 28e1051a39Sopenharmony_ci#endif 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci#include <openssl/x509.h> 31e1051a39Sopenharmony_ci#include "crypto/x509.h" 32e1051a39Sopenharmony_ci#include "x509_local.h" 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_cistruct lookup_dir_hashes_st { 35e1051a39Sopenharmony_ci unsigned long hash; 36e1051a39Sopenharmony_ci int suffix; 37e1051a39Sopenharmony_ci}; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_cistruct lookup_dir_entry_st { 40e1051a39Sopenharmony_ci char *dir; 41e1051a39Sopenharmony_ci int dir_type; 42e1051a39Sopenharmony_ci STACK_OF(BY_DIR_HASH) *hashes; 43e1051a39Sopenharmony_ci}; 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_citypedef struct lookup_dir_st { 46e1051a39Sopenharmony_ci BUF_MEM *buffer; 47e1051a39Sopenharmony_ci STACK_OF(BY_DIR_ENTRY) *dirs; 48e1051a39Sopenharmony_ci CRYPTO_RWLOCK *lock; 49e1051a39Sopenharmony_ci} BY_DIR; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_cistatic int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, 52e1051a39Sopenharmony_ci char **retp); 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_cistatic int new_dir(X509_LOOKUP *lu); 55e1051a39Sopenharmony_cistatic void free_dir(X509_LOOKUP *lu); 56e1051a39Sopenharmony_cistatic int add_cert_dir(BY_DIR *ctx, const char *dir, int type); 57e1051a39Sopenharmony_cistatic int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, 58e1051a39Sopenharmony_ci const X509_NAME *name, X509_OBJECT *ret); 59e1051a39Sopenharmony_cistatic int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, 60e1051a39Sopenharmony_ci const X509_NAME *name, X509_OBJECT *ret, 61e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq); 62e1051a39Sopenharmony_cistatic X509_LOOKUP_METHOD x509_dir_lookup = { 63e1051a39Sopenharmony_ci "Load certs from files in a directory", 64e1051a39Sopenharmony_ci new_dir, /* new_item */ 65e1051a39Sopenharmony_ci free_dir, /* free */ 66e1051a39Sopenharmony_ci NULL, /* init */ 67e1051a39Sopenharmony_ci NULL, /* shutdown */ 68e1051a39Sopenharmony_ci dir_ctrl, /* ctrl */ 69e1051a39Sopenharmony_ci get_cert_by_subject, /* get_by_subject */ 70e1051a39Sopenharmony_ci NULL, /* get_by_issuer_serial */ 71e1051a39Sopenharmony_ci NULL, /* get_by_fingerprint */ 72e1051a39Sopenharmony_ci NULL, /* get_by_alias */ 73e1051a39Sopenharmony_ci get_cert_by_subject_ex, /* get_by_subject_ex */ 74e1051a39Sopenharmony_ci NULL, /* ctrl_ex */ 75e1051a39Sopenharmony_ci}; 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ciX509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) 78e1051a39Sopenharmony_ci{ 79e1051a39Sopenharmony_ci return &x509_dir_lookup; 80e1051a39Sopenharmony_ci} 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_cistatic int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, 83e1051a39Sopenharmony_ci char **retp) 84e1051a39Sopenharmony_ci{ 85e1051a39Sopenharmony_ci int ret = 0; 86e1051a39Sopenharmony_ci BY_DIR *ld = (BY_DIR *)ctx->method_data; 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci switch (cmd) { 89e1051a39Sopenharmony_ci case X509_L_ADD_DIR: 90e1051a39Sopenharmony_ci if (argl == X509_FILETYPE_DEFAULT) { 91e1051a39Sopenharmony_ci const char *dir = ossl_safe_getenv(X509_get_default_cert_dir_env()); 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (dir) 94e1051a39Sopenharmony_ci ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM); 95e1051a39Sopenharmony_ci else 96e1051a39Sopenharmony_ci ret = add_cert_dir(ld, X509_get_default_cert_dir(), 97e1051a39Sopenharmony_ci X509_FILETYPE_PEM); 98e1051a39Sopenharmony_ci if (!ret) { 99e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_LOADING_CERT_DIR); 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci } else 102e1051a39Sopenharmony_ci ret = add_cert_dir(ld, argp, (int)argl); 103e1051a39Sopenharmony_ci break; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci return ret; 106e1051a39Sopenharmony_ci} 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_cistatic int new_dir(X509_LOOKUP *lu) 109e1051a39Sopenharmony_ci{ 110e1051a39Sopenharmony_ci BY_DIR *a = OPENSSL_malloc(sizeof(*a)); 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci if (a == NULL) { 113e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 114e1051a39Sopenharmony_ci return 0; 115e1051a39Sopenharmony_ci } 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci if ((a->buffer = BUF_MEM_new()) == NULL) { 118e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 119e1051a39Sopenharmony_ci goto err; 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci a->dirs = NULL; 122e1051a39Sopenharmony_ci a->lock = CRYPTO_THREAD_lock_new(); 123e1051a39Sopenharmony_ci if (a->lock == NULL) { 124e1051a39Sopenharmony_ci BUF_MEM_free(a->buffer); 125e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 126e1051a39Sopenharmony_ci goto err; 127e1051a39Sopenharmony_ci } 128e1051a39Sopenharmony_ci lu->method_data = a; 129e1051a39Sopenharmony_ci return 1; 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci err: 132e1051a39Sopenharmony_ci OPENSSL_free(a); 133e1051a39Sopenharmony_ci return 0; 134e1051a39Sopenharmony_ci} 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_cistatic void by_dir_hash_free(BY_DIR_HASH *hash) 137e1051a39Sopenharmony_ci{ 138e1051a39Sopenharmony_ci OPENSSL_free(hash); 139e1051a39Sopenharmony_ci} 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_cistatic int by_dir_hash_cmp(const BY_DIR_HASH *const *a, 142e1051a39Sopenharmony_ci const BY_DIR_HASH *const *b) 143e1051a39Sopenharmony_ci{ 144e1051a39Sopenharmony_ci if ((*a)->hash > (*b)->hash) 145e1051a39Sopenharmony_ci return 1; 146e1051a39Sopenharmony_ci if ((*a)->hash < (*b)->hash) 147e1051a39Sopenharmony_ci return -1; 148e1051a39Sopenharmony_ci return 0; 149e1051a39Sopenharmony_ci} 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_cistatic void by_dir_entry_free(BY_DIR_ENTRY *ent) 152e1051a39Sopenharmony_ci{ 153e1051a39Sopenharmony_ci OPENSSL_free(ent->dir); 154e1051a39Sopenharmony_ci sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); 155e1051a39Sopenharmony_ci OPENSSL_free(ent); 156e1051a39Sopenharmony_ci} 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_cistatic void free_dir(X509_LOOKUP *lu) 159e1051a39Sopenharmony_ci{ 160e1051a39Sopenharmony_ci BY_DIR *a = (BY_DIR *)lu->method_data; 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); 163e1051a39Sopenharmony_ci BUF_MEM_free(a->buffer); 164e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(a->lock); 165e1051a39Sopenharmony_ci OPENSSL_free(a); 166e1051a39Sopenharmony_ci} 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_cistatic int add_cert_dir(BY_DIR *ctx, const char *dir, int type) 169e1051a39Sopenharmony_ci{ 170e1051a39Sopenharmony_ci int j; 171e1051a39Sopenharmony_ci size_t len; 172e1051a39Sopenharmony_ci const char *s, *ss, *p; 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ci if (dir == NULL || *dir == '\0') { 175e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_INVALID_DIRECTORY); 176e1051a39Sopenharmony_ci return 0; 177e1051a39Sopenharmony_ci } 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci s = dir; 180e1051a39Sopenharmony_ci p = s; 181e1051a39Sopenharmony_ci do { 182e1051a39Sopenharmony_ci if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) { 183e1051a39Sopenharmony_ci BY_DIR_ENTRY *ent; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci ss = s; 186e1051a39Sopenharmony_ci s = p + 1; 187e1051a39Sopenharmony_ci len = p - ss; 188e1051a39Sopenharmony_ci if (len == 0) 189e1051a39Sopenharmony_ci continue; 190e1051a39Sopenharmony_ci for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { 191e1051a39Sopenharmony_ci ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); 192e1051a39Sopenharmony_ci if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0) 193e1051a39Sopenharmony_ci break; 194e1051a39Sopenharmony_ci } 195e1051a39Sopenharmony_ci if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) 196e1051a39Sopenharmony_ci continue; 197e1051a39Sopenharmony_ci if (ctx->dirs == NULL) { 198e1051a39Sopenharmony_ci ctx->dirs = sk_BY_DIR_ENTRY_new_null(); 199e1051a39Sopenharmony_ci if (!ctx->dirs) { 200e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 201e1051a39Sopenharmony_ci return 0; 202e1051a39Sopenharmony_ci } 203e1051a39Sopenharmony_ci } 204e1051a39Sopenharmony_ci ent = OPENSSL_malloc(sizeof(*ent)); 205e1051a39Sopenharmony_ci if (ent == NULL) { 206e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 207e1051a39Sopenharmony_ci return 0; 208e1051a39Sopenharmony_ci } 209e1051a39Sopenharmony_ci ent->dir_type = type; 210e1051a39Sopenharmony_ci ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); 211e1051a39Sopenharmony_ci ent->dir = OPENSSL_strndup(ss, len); 212e1051a39Sopenharmony_ci if (ent->dir == NULL || ent->hashes == NULL) { 213e1051a39Sopenharmony_ci by_dir_entry_free(ent); 214e1051a39Sopenharmony_ci return 0; 215e1051a39Sopenharmony_ci } 216e1051a39Sopenharmony_ci if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { 217e1051a39Sopenharmony_ci by_dir_entry_free(ent); 218e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 219e1051a39Sopenharmony_ci return 0; 220e1051a39Sopenharmony_ci } 221e1051a39Sopenharmony_ci } 222e1051a39Sopenharmony_ci } while (*p++ != '\0'); 223e1051a39Sopenharmony_ci return 1; 224e1051a39Sopenharmony_ci} 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_cistatic int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, 227e1051a39Sopenharmony_ci const X509_NAME *name, X509_OBJECT *ret, 228e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 229e1051a39Sopenharmony_ci{ 230e1051a39Sopenharmony_ci BY_DIR *ctx; 231e1051a39Sopenharmony_ci union { 232e1051a39Sopenharmony_ci X509 st_x509; 233e1051a39Sopenharmony_ci X509_CRL crl; 234e1051a39Sopenharmony_ci } data; 235e1051a39Sopenharmony_ci int ok = 0; 236e1051a39Sopenharmony_ci int i, j, k; 237e1051a39Sopenharmony_ci unsigned long h; 238e1051a39Sopenharmony_ci BUF_MEM *b = NULL; 239e1051a39Sopenharmony_ci X509_OBJECT stmp, *tmp; 240e1051a39Sopenharmony_ci const char *postfix = ""; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci if (name == NULL) 243e1051a39Sopenharmony_ci return 0; 244e1051a39Sopenharmony_ci 245e1051a39Sopenharmony_ci stmp.type = type; 246e1051a39Sopenharmony_ci if (type == X509_LU_X509) { 247e1051a39Sopenharmony_ci data.st_x509.cert_info.subject = (X509_NAME *)name; /* won't modify it */ 248e1051a39Sopenharmony_ci stmp.data.x509 = &data.st_x509; 249e1051a39Sopenharmony_ci } else if (type == X509_LU_CRL) { 250e1051a39Sopenharmony_ci data.crl.crl.issuer = (X509_NAME *)name; /* won't modify it */ 251e1051a39Sopenharmony_ci stmp.data.crl = &data.crl; 252e1051a39Sopenharmony_ci postfix = "r"; 253e1051a39Sopenharmony_ci } else { 254e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, X509_R_WRONG_LOOKUP_TYPE); 255e1051a39Sopenharmony_ci goto finish; 256e1051a39Sopenharmony_ci } 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci if ((b = BUF_MEM_new()) == NULL) { 259e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB); 260e1051a39Sopenharmony_ci goto finish; 261e1051a39Sopenharmony_ci } 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci ctx = (BY_DIR *)xl->method_data; 264e1051a39Sopenharmony_ci h = X509_NAME_hash_ex(name, libctx, propq, &i); 265e1051a39Sopenharmony_ci if (i == 0) 266e1051a39Sopenharmony_ci goto finish; 267e1051a39Sopenharmony_ci for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { 268e1051a39Sopenharmony_ci BY_DIR_ENTRY *ent; 269e1051a39Sopenharmony_ci int idx; 270e1051a39Sopenharmony_ci BY_DIR_HASH htmp, *hent; 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); 273e1051a39Sopenharmony_ci j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; 274e1051a39Sopenharmony_ci if (!BUF_MEM_grow(b, j)) { 275e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 276e1051a39Sopenharmony_ci goto finish; 277e1051a39Sopenharmony_ci } 278e1051a39Sopenharmony_ci if (type == X509_LU_CRL && ent->hashes) { 279e1051a39Sopenharmony_ci htmp.hash = h; 280e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(ctx->lock)) 281e1051a39Sopenharmony_ci goto finish; 282e1051a39Sopenharmony_ci idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); 283e1051a39Sopenharmony_ci if (idx >= 0) { 284e1051a39Sopenharmony_ci hent = sk_BY_DIR_HASH_value(ent->hashes, idx); 285e1051a39Sopenharmony_ci k = hent->suffix; 286e1051a39Sopenharmony_ci } else { 287e1051a39Sopenharmony_ci hent = NULL; 288e1051a39Sopenharmony_ci k = 0; 289e1051a39Sopenharmony_ci } 290e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 291e1051a39Sopenharmony_ci } else { 292e1051a39Sopenharmony_ci k = 0; 293e1051a39Sopenharmony_ci hent = NULL; 294e1051a39Sopenharmony_ci } 295e1051a39Sopenharmony_ci for (;;) { 296e1051a39Sopenharmony_ci char c = '/'; 297e1051a39Sopenharmony_ci 298e1051a39Sopenharmony_ci#ifdef OPENSSL_SYS_VMS 299e1051a39Sopenharmony_ci c = ent->dir[strlen(ent->dir) - 1]; 300e1051a39Sopenharmony_ci if (c != ':' && c != '>' && c != ']') { 301e1051a39Sopenharmony_ci /* 302e1051a39Sopenharmony_ci * If no separator is present, we assume the directory 303e1051a39Sopenharmony_ci * specifier is a logical name, and add a colon. We really 304e1051a39Sopenharmony_ci * should use better VMS routines for merging things like 305e1051a39Sopenharmony_ci * this, but this will do for now... -- Richard Levitte 306e1051a39Sopenharmony_ci */ 307e1051a39Sopenharmony_ci c = ':'; 308e1051a39Sopenharmony_ci } else { 309e1051a39Sopenharmony_ci c = '\0'; 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_ci if (c == '\0') { 313e1051a39Sopenharmony_ci /* 314e1051a39Sopenharmony_ci * This is special. When c == '\0', no directory separator 315e1051a39Sopenharmony_ci * should be added. 316e1051a39Sopenharmony_ci */ 317e1051a39Sopenharmony_ci BIO_snprintf(b->data, b->max, 318e1051a39Sopenharmony_ci "%s%08lx.%s%d", ent->dir, h, postfix, k); 319e1051a39Sopenharmony_ci } else 320e1051a39Sopenharmony_ci#endif 321e1051a39Sopenharmony_ci { 322e1051a39Sopenharmony_ci BIO_snprintf(b->data, b->max, 323e1051a39Sopenharmony_ci "%s%c%08lx.%s%d", ent->dir, c, h, postfix, k); 324e1051a39Sopenharmony_ci } 325e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 326e1051a39Sopenharmony_ci# ifdef _WIN32 327e1051a39Sopenharmony_ci# define stat _stat 328e1051a39Sopenharmony_ci# endif 329e1051a39Sopenharmony_ci { 330e1051a39Sopenharmony_ci struct stat st; 331e1051a39Sopenharmony_ci if (stat(b->data, &st) < 0) 332e1051a39Sopenharmony_ci break; 333e1051a39Sopenharmony_ci } 334e1051a39Sopenharmony_ci#endif 335e1051a39Sopenharmony_ci /* found one. */ 336e1051a39Sopenharmony_ci if (type == X509_LU_X509) { 337e1051a39Sopenharmony_ci if ((X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx, 338e1051a39Sopenharmony_ci propq)) == 0) 339e1051a39Sopenharmony_ci break; 340e1051a39Sopenharmony_ci } else if (type == X509_LU_CRL) { 341e1051a39Sopenharmony_ci if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0) 342e1051a39Sopenharmony_ci break; 343e1051a39Sopenharmony_ci } 344e1051a39Sopenharmony_ci /* else case will caught higher up */ 345e1051a39Sopenharmony_ci k++; 346e1051a39Sopenharmony_ci } 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci /* 349e1051a39Sopenharmony_ci * we have added it to the cache so now pull it out again 350e1051a39Sopenharmony_ci */ 351e1051a39Sopenharmony_ci X509_STORE_lock(xl->store_ctx); 352e1051a39Sopenharmony_ci j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); 353e1051a39Sopenharmony_ci tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); 354e1051a39Sopenharmony_ci X509_STORE_unlock(xl->store_ctx); 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci /* 357e1051a39Sopenharmony_ci * If a CRL, update the last file suffix added for this. 358e1051a39Sopenharmony_ci * We don't need to add an entry if k is 0 as this is the initial value. 359e1051a39Sopenharmony_ci * This avoids the need for a write lock and sort operation in the 360e1051a39Sopenharmony_ci * simple case where no CRL is present for a hash. 361e1051a39Sopenharmony_ci */ 362e1051a39Sopenharmony_ci if (type == X509_LU_CRL && k > 0) { 363e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(ctx->lock)) 364e1051a39Sopenharmony_ci goto finish; 365e1051a39Sopenharmony_ci /* 366e1051a39Sopenharmony_ci * Look for entry again in case another thread added an entry 367e1051a39Sopenharmony_ci * first. 368e1051a39Sopenharmony_ci */ 369e1051a39Sopenharmony_ci if (hent == NULL) { 370e1051a39Sopenharmony_ci htmp.hash = h; 371e1051a39Sopenharmony_ci idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); 372e1051a39Sopenharmony_ci hent = sk_BY_DIR_HASH_value(ent->hashes, idx); 373e1051a39Sopenharmony_ci } 374e1051a39Sopenharmony_ci if (hent == NULL) { 375e1051a39Sopenharmony_ci hent = OPENSSL_malloc(sizeof(*hent)); 376e1051a39Sopenharmony_ci if (hent == NULL) { 377e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 378e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 379e1051a39Sopenharmony_ci ok = 0; 380e1051a39Sopenharmony_ci goto finish; 381e1051a39Sopenharmony_ci } 382e1051a39Sopenharmony_ci hent->hash = h; 383e1051a39Sopenharmony_ci hent->suffix = k; 384e1051a39Sopenharmony_ci if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { 385e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 386e1051a39Sopenharmony_ci OPENSSL_free(hent); 387e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); 388e1051a39Sopenharmony_ci ok = 0; 389e1051a39Sopenharmony_ci goto finish; 390e1051a39Sopenharmony_ci } 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci /* 393e1051a39Sopenharmony_ci * Ensure stack is sorted so that subsequent sk_BY_DIR_HASH_find 394e1051a39Sopenharmony_ci * will not mutate the stack and therefore require a write lock. 395e1051a39Sopenharmony_ci */ 396e1051a39Sopenharmony_ci sk_BY_DIR_HASH_sort(ent->hashes); 397e1051a39Sopenharmony_ci } else if (hent->suffix < k) { 398e1051a39Sopenharmony_ci hent->suffix = k; 399e1051a39Sopenharmony_ci } 400e1051a39Sopenharmony_ci 401e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(ctx->lock); 402e1051a39Sopenharmony_ci 403e1051a39Sopenharmony_ci } 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci if (tmp != NULL) { 406e1051a39Sopenharmony_ci ok = 1; 407e1051a39Sopenharmony_ci ret->type = tmp->type; 408e1051a39Sopenharmony_ci memcpy(&ret->data, &tmp->data, sizeof(ret->data)); 409e1051a39Sopenharmony_ci 410e1051a39Sopenharmony_ci /* 411e1051a39Sopenharmony_ci * Clear any errors that might have been raised processing empty 412e1051a39Sopenharmony_ci * or malformed files. 413e1051a39Sopenharmony_ci */ 414e1051a39Sopenharmony_ci ERR_clear_error(); 415e1051a39Sopenharmony_ci 416e1051a39Sopenharmony_ci goto finish; 417e1051a39Sopenharmony_ci } 418e1051a39Sopenharmony_ci } 419e1051a39Sopenharmony_ci finish: 420e1051a39Sopenharmony_ci BUF_MEM_free(b); 421e1051a39Sopenharmony_ci return ok; 422e1051a39Sopenharmony_ci} 423e1051a39Sopenharmony_ci 424e1051a39Sopenharmony_cistatic int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, 425e1051a39Sopenharmony_ci const X509_NAME *name, X509_OBJECT *ret) 426e1051a39Sopenharmony_ci{ 427e1051a39Sopenharmony_ci return get_cert_by_subject_ex(xl, type, name, ret, NULL, NULL); 428e1051a39Sopenharmony_ci} 429