1*b077aed3SPierre Pronchery /* 2*b077aed3SPierre Pronchery * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3*b077aed3SPierre Pronchery * 4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5*b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6*b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at 7*b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html 8*b077aed3SPierre Pronchery */ 9*b077aed3SPierre Pronchery 10*b077aed3SPierre Pronchery #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) 11*b077aed3SPierre Pronchery /* 12*b077aed3SPierre Pronchery * On VMS, you need to define this to get the declaration of fileno(). The 13*b077aed3SPierre Pronchery * value 2 is to make sure no function defined in POSIX-2 is left undefined. 14*b077aed3SPierre Pronchery */ 15*b077aed3SPierre Pronchery # define _POSIX_C_SOURCE 2 16*b077aed3SPierre Pronchery #endif 17*b077aed3SPierre Pronchery 18*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_ENGINE 19*b077aed3SPierre Pronchery /* We need to use some deprecated APIs */ 20*b077aed3SPierre Pronchery # define OPENSSL_SUPPRESS_DEPRECATED 21*b077aed3SPierre Pronchery # include <openssl/engine.h> 22*b077aed3SPierre Pronchery #endif 23*b077aed3SPierre Pronchery 24*b077aed3SPierre Pronchery #include <stdio.h> 25*b077aed3SPierre Pronchery #include <stdlib.h> 26*b077aed3SPierre Pronchery #include <string.h> 27*b077aed3SPierre Pronchery #include <sys/types.h> 28*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 29*b077aed3SPierre Pronchery # include <sys/stat.h> 30*b077aed3SPierre Pronchery # include <fcntl.h> 31*b077aed3SPierre Pronchery #endif 32*b077aed3SPierre Pronchery #include <ctype.h> 33*b077aed3SPierre Pronchery #include <errno.h> 34*b077aed3SPierre Pronchery #include <openssl/err.h> 35*b077aed3SPierre Pronchery #include <openssl/x509.h> 36*b077aed3SPierre Pronchery #include <openssl/x509v3.h> 37*b077aed3SPierre Pronchery #include <openssl/http.h> 38*b077aed3SPierre Pronchery #include <openssl/pem.h> 39*b077aed3SPierre Pronchery #include <openssl/store.h> 40*b077aed3SPierre Pronchery #include <openssl/pkcs12.h> 41*b077aed3SPierre Pronchery #include <openssl/ui.h> 42*b077aed3SPierre Pronchery #include <openssl/safestack.h> 43*b077aed3SPierre Pronchery #include <openssl/rsa.h> 44*b077aed3SPierre Pronchery #include <openssl/rand.h> 45*b077aed3SPierre Pronchery #include <openssl/bn.h> 46*b077aed3SPierre Pronchery #include <openssl/ssl.h> 47*b077aed3SPierre Pronchery #include <openssl/store.h> 48*b077aed3SPierre Pronchery #include <openssl/core_names.h> 49*b077aed3SPierre Pronchery #include "s_apps.h" 50*b077aed3SPierre Pronchery #include "apps.h" 51*b077aed3SPierre Pronchery 52*b077aed3SPierre Pronchery #ifdef _WIN32 53*b077aed3SPierre Pronchery static int WIN32_rename(const char *from, const char *to); 54*b077aed3SPierre Pronchery # define rename(from,to) WIN32_rename((from),(to)) 55*b077aed3SPierre Pronchery #endif 56*b077aed3SPierre Pronchery 57*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 58*b077aed3SPierre Pronchery # include <conio.h> 59*b077aed3SPierre Pronchery #endif 60*b077aed3SPierre Pronchery 61*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) || defined(__BORLANDC__) 62*b077aed3SPierre Pronchery # define _kbhit kbhit 63*b077aed3SPierre Pronchery #endif 64*b077aed3SPierre Pronchery 65*b077aed3SPierre Pronchery static BIO *bio_open_default_(const char *filename, char mode, int format, 66*b077aed3SPierre Pronchery int quiet); 67*b077aed3SPierre Pronchery 68*b077aed3SPierre Pronchery #define PASS_SOURCE_SIZE_MAX 4 69*b077aed3SPierre Pronchery 70*b077aed3SPierre Pronchery DEFINE_STACK_OF(CONF) 71*b077aed3SPierre Pronchery 72*b077aed3SPierre Pronchery typedef struct { 73*b077aed3SPierre Pronchery const char *name; 74*b077aed3SPierre Pronchery unsigned long flag; 75*b077aed3SPierre Pronchery unsigned long mask; 76*b077aed3SPierre Pronchery } NAME_EX_TBL; 77*b077aed3SPierre Pronchery 78*b077aed3SPierre Pronchery static int set_table_opts(unsigned long *flags, const char *arg, 79*b077aed3SPierre Pronchery const NAME_EX_TBL * in_tbl); 80*b077aed3SPierre Pronchery static int set_multi_opts(unsigned long *flags, const char *arg, 81*b077aed3SPierre Pronchery const NAME_EX_TBL * in_tbl); 82*b077aed3SPierre Pronchery static 83*b077aed3SPierre Pronchery int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, 84*b077aed3SPierre Pronchery const char *pass, const char *desc, 85*b077aed3SPierre Pronchery EVP_PKEY **ppkey, EVP_PKEY **ppubkey, 86*b077aed3SPierre Pronchery EVP_PKEY **pparams, 87*b077aed3SPierre Pronchery X509 **pcert, STACK_OF(X509) **pcerts, 88*b077aed3SPierre Pronchery X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls, 89*b077aed3SPierre Pronchery int suppress_decode_errors); 90*b077aed3SPierre Pronchery 91*b077aed3SPierre Pronchery int app_init(long mesgwin); 92*b077aed3SPierre Pronchery 93*b077aed3SPierre Pronchery int chopup_args(ARGS *arg, char *buf) 94*b077aed3SPierre Pronchery { 95*b077aed3SPierre Pronchery int quoted; 96*b077aed3SPierre Pronchery char c = '\0', *p = NULL; 97*b077aed3SPierre Pronchery 98*b077aed3SPierre Pronchery arg->argc = 0; 99*b077aed3SPierre Pronchery if (arg->size == 0) { 100*b077aed3SPierre Pronchery arg->size = 20; 101*b077aed3SPierre Pronchery arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); 102*b077aed3SPierre Pronchery } 103*b077aed3SPierre Pronchery 104*b077aed3SPierre Pronchery for (p = buf;;) { 105*b077aed3SPierre Pronchery /* Skip whitespace. */ 106*b077aed3SPierre Pronchery while (*p && isspace(_UC(*p))) 107*b077aed3SPierre Pronchery p++; 108*b077aed3SPierre Pronchery if (*p == '\0') 109*b077aed3SPierre Pronchery break; 110*b077aed3SPierre Pronchery 111*b077aed3SPierre Pronchery /* The start of something good :-) */ 112*b077aed3SPierre Pronchery if (arg->argc >= arg->size) { 113*b077aed3SPierre Pronchery char **tmp; 114*b077aed3SPierre Pronchery arg->size += 20; 115*b077aed3SPierre Pronchery tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); 116*b077aed3SPierre Pronchery if (tmp == NULL) 117*b077aed3SPierre Pronchery return 0; 118*b077aed3SPierre Pronchery arg->argv = tmp; 119*b077aed3SPierre Pronchery } 120*b077aed3SPierre Pronchery quoted = *p == '\'' || *p == '"'; 121*b077aed3SPierre Pronchery if (quoted) 122*b077aed3SPierre Pronchery c = *p++; 123*b077aed3SPierre Pronchery arg->argv[arg->argc++] = p; 124*b077aed3SPierre Pronchery 125*b077aed3SPierre Pronchery /* now look for the end of this */ 126*b077aed3SPierre Pronchery if (quoted) { 127*b077aed3SPierre Pronchery while (*p && *p != c) 128*b077aed3SPierre Pronchery p++; 129*b077aed3SPierre Pronchery *p++ = '\0'; 130*b077aed3SPierre Pronchery } else { 131*b077aed3SPierre Pronchery while (*p && !isspace(_UC(*p))) 132*b077aed3SPierre Pronchery p++; 133*b077aed3SPierre Pronchery if (*p) 134*b077aed3SPierre Pronchery *p++ = '\0'; 135*b077aed3SPierre Pronchery } 136*b077aed3SPierre Pronchery } 137*b077aed3SPierre Pronchery arg->argv[arg->argc] = NULL; 138*b077aed3SPierre Pronchery return 1; 139*b077aed3SPierre Pronchery } 140*b077aed3SPierre Pronchery 141*b077aed3SPierre Pronchery #ifndef APP_INIT 142*b077aed3SPierre Pronchery int app_init(long mesgwin) 143*b077aed3SPierre Pronchery { 144*b077aed3SPierre Pronchery return 1; 145*b077aed3SPierre Pronchery } 146*b077aed3SPierre Pronchery #endif 147*b077aed3SPierre Pronchery 148*b077aed3SPierre Pronchery int ctx_set_verify_locations(SSL_CTX *ctx, 149*b077aed3SPierre Pronchery const char *CAfile, int noCAfile, 150*b077aed3SPierre Pronchery const char *CApath, int noCApath, 151*b077aed3SPierre Pronchery const char *CAstore, int noCAstore) 152*b077aed3SPierre Pronchery { 153*b077aed3SPierre Pronchery if (CAfile == NULL && CApath == NULL && CAstore == NULL) { 154*b077aed3SPierre Pronchery if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) 155*b077aed3SPierre Pronchery return 0; 156*b077aed3SPierre Pronchery if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) 157*b077aed3SPierre Pronchery return 0; 158*b077aed3SPierre Pronchery if (!noCAstore && SSL_CTX_set_default_verify_store(ctx) <= 0) 159*b077aed3SPierre Pronchery return 0; 160*b077aed3SPierre Pronchery 161*b077aed3SPierre Pronchery return 1; 162*b077aed3SPierre Pronchery } 163*b077aed3SPierre Pronchery 164*b077aed3SPierre Pronchery if (CAfile != NULL && !SSL_CTX_load_verify_file(ctx, CAfile)) 165*b077aed3SPierre Pronchery return 0; 166*b077aed3SPierre Pronchery if (CApath != NULL && !SSL_CTX_load_verify_dir(ctx, CApath)) 167*b077aed3SPierre Pronchery return 0; 168*b077aed3SPierre Pronchery if (CAstore != NULL && !SSL_CTX_load_verify_store(ctx, CAstore)) 169*b077aed3SPierre Pronchery return 0; 170*b077aed3SPierre Pronchery return 1; 171*b077aed3SPierre Pronchery } 172*b077aed3SPierre Pronchery 173*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_CT 174*b077aed3SPierre Pronchery 175*b077aed3SPierre Pronchery int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) 176*b077aed3SPierre Pronchery { 177*b077aed3SPierre Pronchery if (path == NULL) 178*b077aed3SPierre Pronchery return SSL_CTX_set_default_ctlog_list_file(ctx); 179*b077aed3SPierre Pronchery 180*b077aed3SPierre Pronchery return SSL_CTX_set_ctlog_list_file(ctx, path); 181*b077aed3SPierre Pronchery } 182*b077aed3SPierre Pronchery 183*b077aed3SPierre Pronchery #endif 184*b077aed3SPierre Pronchery 185*b077aed3SPierre Pronchery static unsigned long nmflag = 0; 186*b077aed3SPierre Pronchery static char nmflag_set = 0; 187*b077aed3SPierre Pronchery 188*b077aed3SPierre Pronchery int set_nameopt(const char *arg) 189*b077aed3SPierre Pronchery { 190*b077aed3SPierre Pronchery int ret = set_name_ex(&nmflag, arg); 191*b077aed3SPierre Pronchery 192*b077aed3SPierre Pronchery if (ret) 193*b077aed3SPierre Pronchery nmflag_set = 1; 194*b077aed3SPierre Pronchery 195*b077aed3SPierre Pronchery return ret; 196*b077aed3SPierre Pronchery } 197*b077aed3SPierre Pronchery 198*b077aed3SPierre Pronchery unsigned long get_nameopt(void) 199*b077aed3SPierre Pronchery { 200*b077aed3SPierre Pronchery return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; 201*b077aed3SPierre Pronchery } 202*b077aed3SPierre Pronchery 203*b077aed3SPierre Pronchery void dump_cert_text(BIO *out, X509 *x) 204*b077aed3SPierre Pronchery { 205*b077aed3SPierre Pronchery print_name(out, "subject=", X509_get_subject_name(x)); 206*b077aed3SPierre Pronchery print_name(out, "issuer=", X509_get_issuer_name(x)); 207*b077aed3SPierre Pronchery } 208*b077aed3SPierre Pronchery 209*b077aed3SPierre Pronchery int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata) 210*b077aed3SPierre Pronchery { 211*b077aed3SPierre Pronchery return password_callback(buf, bufsiz, verify, (PW_CB_DATA *)userdata); 212*b077aed3SPierre Pronchery } 213*b077aed3SPierre Pronchery 214*b077aed3SPierre Pronchery 215*b077aed3SPierre Pronchery static char *app_get_pass(const char *arg, int keepbio); 216*b077aed3SPierre Pronchery 217*b077aed3SPierre Pronchery char *get_passwd(const char *pass, const char *desc) 218*b077aed3SPierre Pronchery { 219*b077aed3SPierre Pronchery char *result = NULL; 220*b077aed3SPierre Pronchery 221*b077aed3SPierre Pronchery if (desc == NULL) 222*b077aed3SPierre Pronchery desc = "<unknown>"; 223*b077aed3SPierre Pronchery if (!app_passwd(pass, NULL, &result, NULL)) 224*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error getting password for %s\n", desc); 225*b077aed3SPierre Pronchery if (pass != NULL && result == NULL) { 226*b077aed3SPierre Pronchery BIO_printf(bio_err, 227*b077aed3SPierre Pronchery "Trying plain input string (better precede with 'pass:')\n"); 228*b077aed3SPierre Pronchery result = OPENSSL_strdup(pass); 229*b077aed3SPierre Pronchery if (result == NULL) 230*b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory getting password for %s\n", desc); 231*b077aed3SPierre Pronchery } 232*b077aed3SPierre Pronchery return result; 233*b077aed3SPierre Pronchery } 234*b077aed3SPierre Pronchery 235*b077aed3SPierre Pronchery int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) 236*b077aed3SPierre Pronchery { 237*b077aed3SPierre Pronchery int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0; 238*b077aed3SPierre Pronchery 239*b077aed3SPierre Pronchery if (arg1 != NULL) { 240*b077aed3SPierre Pronchery *pass1 = app_get_pass(arg1, same); 241*b077aed3SPierre Pronchery if (*pass1 == NULL) 242*b077aed3SPierre Pronchery return 0; 243*b077aed3SPierre Pronchery } else if (pass1 != NULL) { 244*b077aed3SPierre Pronchery *pass1 = NULL; 245*b077aed3SPierre Pronchery } 246*b077aed3SPierre Pronchery if (arg2 != NULL) { 247*b077aed3SPierre Pronchery *pass2 = app_get_pass(arg2, same ? 2 : 0); 248*b077aed3SPierre Pronchery if (*pass2 == NULL) 249*b077aed3SPierre Pronchery return 0; 250*b077aed3SPierre Pronchery } else if (pass2 != NULL) { 251*b077aed3SPierre Pronchery *pass2 = NULL; 252*b077aed3SPierre Pronchery } 253*b077aed3SPierre Pronchery return 1; 254*b077aed3SPierre Pronchery } 255*b077aed3SPierre Pronchery 256*b077aed3SPierre Pronchery static char *app_get_pass(const char *arg, int keepbio) 257*b077aed3SPierre Pronchery { 258*b077aed3SPierre Pronchery static BIO *pwdbio = NULL; 259*b077aed3SPierre Pronchery char *tmp, tpass[APP_PASS_LEN]; 260*b077aed3SPierre Pronchery int i; 261*b077aed3SPierre Pronchery 262*b077aed3SPierre Pronchery /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */ 263*b077aed3SPierre Pronchery if (strncmp(arg, "pass:", 5) == 0) 264*b077aed3SPierre Pronchery return OPENSSL_strdup(arg + 5); 265*b077aed3SPierre Pronchery if (strncmp(arg, "env:", 4) == 0) { 266*b077aed3SPierre Pronchery tmp = getenv(arg + 4); 267*b077aed3SPierre Pronchery if (tmp == NULL) { 268*b077aed3SPierre Pronchery BIO_printf(bio_err, "No environment variable %s\n", arg + 4); 269*b077aed3SPierre Pronchery return NULL; 270*b077aed3SPierre Pronchery } 271*b077aed3SPierre Pronchery return OPENSSL_strdup(tmp); 272*b077aed3SPierre Pronchery } 273*b077aed3SPierre Pronchery if (!keepbio || pwdbio == NULL) { 274*b077aed3SPierre Pronchery if (strncmp(arg, "file:", 5) == 0) { 275*b077aed3SPierre Pronchery pwdbio = BIO_new_file(arg + 5, "r"); 276*b077aed3SPierre Pronchery if (pwdbio == NULL) { 277*b077aed3SPierre Pronchery BIO_printf(bio_err, "Can't open file %s\n", arg + 5); 278*b077aed3SPierre Pronchery return NULL; 279*b077aed3SPierre Pronchery } 280*b077aed3SPierre Pronchery #if !defined(_WIN32) 281*b077aed3SPierre Pronchery /* 282*b077aed3SPierre Pronchery * Under _WIN32, which covers even Win64 and CE, file 283*b077aed3SPierre Pronchery * descriptors referenced by BIO_s_fd are not inherited 284*b077aed3SPierre Pronchery * by child process and therefore below is not an option. 285*b077aed3SPierre Pronchery * It could have been an option if bss_fd.c was operating 286*b077aed3SPierre Pronchery * on real Windows descriptors, such as those obtained 287*b077aed3SPierre Pronchery * with CreateFile. 288*b077aed3SPierre Pronchery */ 289*b077aed3SPierre Pronchery } else if (strncmp(arg, "fd:", 3) == 0) { 290*b077aed3SPierre Pronchery BIO *btmp; 291*b077aed3SPierre Pronchery i = atoi(arg + 3); 292*b077aed3SPierre Pronchery if (i >= 0) 293*b077aed3SPierre Pronchery pwdbio = BIO_new_fd(i, BIO_NOCLOSE); 294*b077aed3SPierre Pronchery if ((i < 0) || pwdbio == NULL) { 295*b077aed3SPierre Pronchery BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); 296*b077aed3SPierre Pronchery return NULL; 297*b077aed3SPierre Pronchery } 298*b077aed3SPierre Pronchery /* 299*b077aed3SPierre Pronchery * Can't do BIO_gets on an fd BIO so add a buffering BIO 300*b077aed3SPierre Pronchery */ 301*b077aed3SPierre Pronchery btmp = BIO_new(BIO_f_buffer()); 302*b077aed3SPierre Pronchery if (btmp == NULL) { 303*b077aed3SPierre Pronchery BIO_free_all(pwdbio); 304*b077aed3SPierre Pronchery pwdbio = NULL; 305*b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory\n"); 306*b077aed3SPierre Pronchery return NULL; 307*b077aed3SPierre Pronchery } 308*b077aed3SPierre Pronchery pwdbio = BIO_push(btmp, pwdbio); 309*b077aed3SPierre Pronchery #endif 310*b077aed3SPierre Pronchery } else if (strcmp(arg, "stdin") == 0) { 311*b077aed3SPierre Pronchery unbuffer(stdin); 312*b077aed3SPierre Pronchery pwdbio = dup_bio_in(FORMAT_TEXT); 313*b077aed3SPierre Pronchery if (pwdbio == NULL) { 314*b077aed3SPierre Pronchery BIO_printf(bio_err, "Can't open BIO for stdin\n"); 315*b077aed3SPierre Pronchery return NULL; 316*b077aed3SPierre Pronchery } 317*b077aed3SPierre Pronchery } else { 318*b077aed3SPierre Pronchery /* argument syntax error; do not reveal too much about arg */ 319*b077aed3SPierre Pronchery tmp = strchr(arg, ':'); 320*b077aed3SPierre Pronchery if (tmp == NULL || tmp - arg > PASS_SOURCE_SIZE_MAX) 321*b077aed3SPierre Pronchery BIO_printf(bio_err, 322*b077aed3SPierre Pronchery "Invalid password argument, missing ':' within the first %d chars\n", 323*b077aed3SPierre Pronchery PASS_SOURCE_SIZE_MAX + 1); 324*b077aed3SPierre Pronchery else 325*b077aed3SPierre Pronchery BIO_printf(bio_err, 326*b077aed3SPierre Pronchery "Invalid password argument, starting with \"%.*s\"\n", 327*b077aed3SPierre Pronchery (int)(tmp - arg + 1), arg); 328*b077aed3SPierre Pronchery return NULL; 329*b077aed3SPierre Pronchery } 330*b077aed3SPierre Pronchery } 331*b077aed3SPierre Pronchery i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); 332*b077aed3SPierre Pronchery if (keepbio != 1) { 333*b077aed3SPierre Pronchery BIO_free_all(pwdbio); 334*b077aed3SPierre Pronchery pwdbio = NULL; 335*b077aed3SPierre Pronchery } 336*b077aed3SPierre Pronchery if (i <= 0) { 337*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error reading password from BIO\n"); 338*b077aed3SPierre Pronchery return NULL; 339*b077aed3SPierre Pronchery } 340*b077aed3SPierre Pronchery tmp = strchr(tpass, '\n'); 341*b077aed3SPierre Pronchery if (tmp != NULL) 342*b077aed3SPierre Pronchery *tmp = 0; 343*b077aed3SPierre Pronchery return OPENSSL_strdup(tpass); 344*b077aed3SPierre Pronchery } 345*b077aed3SPierre Pronchery 346*b077aed3SPierre Pronchery CONF *app_load_config_bio(BIO *in, const char *filename) 347*b077aed3SPierre Pronchery { 348*b077aed3SPierre Pronchery long errorline = -1; 349*b077aed3SPierre Pronchery CONF *conf; 350*b077aed3SPierre Pronchery int i; 351*b077aed3SPierre Pronchery 352*b077aed3SPierre Pronchery conf = NCONF_new_ex(app_get0_libctx(), NULL); 353*b077aed3SPierre Pronchery i = NCONF_load_bio(conf, in, &errorline); 354*b077aed3SPierre Pronchery if (i > 0) 355*b077aed3SPierre Pronchery return conf; 356*b077aed3SPierre Pronchery 357*b077aed3SPierre Pronchery if (errorline <= 0) { 358*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); 359*b077aed3SPierre Pronchery } else { 360*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), 361*b077aed3SPierre Pronchery errorline); 362*b077aed3SPierre Pronchery } 363*b077aed3SPierre Pronchery if (filename != NULL) 364*b077aed3SPierre Pronchery BIO_printf(bio_err, "config file \"%s\"\n", filename); 365*b077aed3SPierre Pronchery else 366*b077aed3SPierre Pronchery BIO_printf(bio_err, "config input"); 367*b077aed3SPierre Pronchery 368*b077aed3SPierre Pronchery NCONF_free(conf); 369*b077aed3SPierre Pronchery return NULL; 370*b077aed3SPierre Pronchery } 371*b077aed3SPierre Pronchery 372*b077aed3SPierre Pronchery CONF *app_load_config_verbose(const char *filename, int verbose) 373*b077aed3SPierre Pronchery { 374*b077aed3SPierre Pronchery if (verbose) { 375*b077aed3SPierre Pronchery if (*filename == '\0') 376*b077aed3SPierre Pronchery BIO_printf(bio_err, "No configuration used\n"); 377*b077aed3SPierre Pronchery else 378*b077aed3SPierre Pronchery BIO_printf(bio_err, "Using configuration from %s\n", filename); 379*b077aed3SPierre Pronchery } 380*b077aed3SPierre Pronchery return app_load_config_internal(filename, 0); 381*b077aed3SPierre Pronchery } 382*b077aed3SPierre Pronchery 383*b077aed3SPierre Pronchery CONF *app_load_config_internal(const char *filename, int quiet) 384*b077aed3SPierre Pronchery { 385*b077aed3SPierre Pronchery BIO *in; 386*b077aed3SPierre Pronchery CONF *conf; 387*b077aed3SPierre Pronchery 388*b077aed3SPierre Pronchery if (filename == NULL || *filename != '\0') { 389*b077aed3SPierre Pronchery if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL) 390*b077aed3SPierre Pronchery return NULL; 391*b077aed3SPierre Pronchery conf = app_load_config_bio(in, filename); 392*b077aed3SPierre Pronchery BIO_free(in); 393*b077aed3SPierre Pronchery } else { 394*b077aed3SPierre Pronchery /* Return empty config if filename is empty string. */ 395*b077aed3SPierre Pronchery conf = NCONF_new_ex(app_get0_libctx(), NULL); 396*b077aed3SPierre Pronchery } 397*b077aed3SPierre Pronchery return conf; 398*b077aed3SPierre Pronchery } 399*b077aed3SPierre Pronchery 400*b077aed3SPierre Pronchery int app_load_modules(const CONF *config) 401*b077aed3SPierre Pronchery { 402*b077aed3SPierre Pronchery CONF *to_free = NULL; 403*b077aed3SPierre Pronchery 404*b077aed3SPierre Pronchery if (config == NULL) 405*b077aed3SPierre Pronchery config = to_free = app_load_config_quiet(default_config_file); 406*b077aed3SPierre Pronchery if (config == NULL) 407*b077aed3SPierre Pronchery return 1; 408*b077aed3SPierre Pronchery 409*b077aed3SPierre Pronchery if (CONF_modules_load(config, NULL, 0) <= 0) { 410*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); 411*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 412*b077aed3SPierre Pronchery NCONF_free(to_free); 413*b077aed3SPierre Pronchery return 0; 414*b077aed3SPierre Pronchery } 415*b077aed3SPierre Pronchery NCONF_free(to_free); 416*b077aed3SPierre Pronchery return 1; 417*b077aed3SPierre Pronchery } 418*b077aed3SPierre Pronchery 419*b077aed3SPierre Pronchery int add_oid_section(CONF *conf) 420*b077aed3SPierre Pronchery { 421*b077aed3SPierre Pronchery char *p; 422*b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *sktmp; 423*b077aed3SPierre Pronchery CONF_VALUE *cnf; 424*b077aed3SPierre Pronchery int i; 425*b077aed3SPierre Pronchery 426*b077aed3SPierre Pronchery if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { 427*b077aed3SPierre Pronchery ERR_clear_error(); 428*b077aed3SPierre Pronchery return 1; 429*b077aed3SPierre Pronchery } 430*b077aed3SPierre Pronchery if ((sktmp = NCONF_get_section(conf, p)) == NULL) { 431*b077aed3SPierre Pronchery BIO_printf(bio_err, "problem loading oid section %s\n", p); 432*b077aed3SPierre Pronchery return 0; 433*b077aed3SPierre Pronchery } 434*b077aed3SPierre Pronchery for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { 435*b077aed3SPierre Pronchery cnf = sk_CONF_VALUE_value(sktmp, i); 436*b077aed3SPierre Pronchery if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { 437*b077aed3SPierre Pronchery BIO_printf(bio_err, "problem creating object %s=%s\n", 438*b077aed3SPierre Pronchery cnf->name, cnf->value); 439*b077aed3SPierre Pronchery return 0; 440*b077aed3SPierre Pronchery } 441*b077aed3SPierre Pronchery } 442*b077aed3SPierre Pronchery return 1; 443*b077aed3SPierre Pronchery } 444*b077aed3SPierre Pronchery 445*b077aed3SPierre Pronchery CONF *app_load_config_modules(const char *configfile) 446*b077aed3SPierre Pronchery { 447*b077aed3SPierre Pronchery CONF *conf = NULL; 448*b077aed3SPierre Pronchery 449*b077aed3SPierre Pronchery if (configfile != NULL) { 450*b077aed3SPierre Pronchery if ((conf = app_load_config_verbose(configfile, 1)) == NULL) 451*b077aed3SPierre Pronchery return NULL; 452*b077aed3SPierre Pronchery if (configfile != default_config_file && !app_load_modules(conf)) { 453*b077aed3SPierre Pronchery NCONF_free(conf); 454*b077aed3SPierre Pronchery conf = NULL; 455*b077aed3SPierre Pronchery } 456*b077aed3SPierre Pronchery } 457*b077aed3SPierre Pronchery return conf; 458*b077aed3SPierre Pronchery } 459*b077aed3SPierre Pronchery 460*b077aed3SPierre Pronchery #define IS_HTTP(uri) ((uri) != NULL \ 461*b077aed3SPierre Pronchery && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0) 462*b077aed3SPierre Pronchery #define IS_HTTPS(uri) ((uri) != NULL \ 463*b077aed3SPierre Pronchery && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0) 464*b077aed3SPierre Pronchery 465*b077aed3SPierre Pronchery X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, 466*b077aed3SPierre Pronchery const char *pass, const char *desc) 467*b077aed3SPierre Pronchery { 468*b077aed3SPierre Pronchery X509 *cert = NULL; 469*b077aed3SPierre Pronchery 470*b077aed3SPierre Pronchery if (desc == NULL) 471*b077aed3SPierre Pronchery desc = "certificate"; 472*b077aed3SPierre Pronchery if (IS_HTTPS(uri)) 473*b077aed3SPierre Pronchery BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); 474*b077aed3SPierre Pronchery else if (IS_HTTP(uri)) 475*b077aed3SPierre Pronchery cert = X509_load_http(uri, NULL, NULL, 0 /* timeout */); 476*b077aed3SPierre Pronchery else 477*b077aed3SPierre Pronchery (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 478*b077aed3SPierre Pronchery NULL, NULL, NULL, &cert, NULL, NULL, NULL); 479*b077aed3SPierre Pronchery if (cert == NULL) { 480*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to load %s\n", desc); 481*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 482*b077aed3SPierre Pronchery } 483*b077aed3SPierre Pronchery return cert; 484*b077aed3SPierre Pronchery } 485*b077aed3SPierre Pronchery 486*b077aed3SPierre Pronchery X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, 487*b077aed3SPierre Pronchery const char *desc) 488*b077aed3SPierre Pronchery { 489*b077aed3SPierre Pronchery X509_CRL *crl = NULL; 490*b077aed3SPierre Pronchery 491*b077aed3SPierre Pronchery if (desc == NULL) 492*b077aed3SPierre Pronchery desc = "CRL"; 493*b077aed3SPierre Pronchery if (IS_HTTPS(uri)) 494*b077aed3SPierre Pronchery BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); 495*b077aed3SPierre Pronchery else if (IS_HTTP(uri)) 496*b077aed3SPierre Pronchery crl = X509_CRL_load_http(uri, NULL, NULL, 0 /* timeout */); 497*b077aed3SPierre Pronchery else 498*b077aed3SPierre Pronchery (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, 499*b077aed3SPierre Pronchery NULL, NULL, NULL, NULL, NULL, &crl, NULL); 500*b077aed3SPierre Pronchery if (crl == NULL) { 501*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to load %s\n", desc); 502*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 503*b077aed3SPierre Pronchery } 504*b077aed3SPierre Pronchery return crl; 505*b077aed3SPierre Pronchery } 506*b077aed3SPierre Pronchery 507*b077aed3SPierre Pronchery X509_REQ *load_csr(const char *file, int format, const char *desc) 508*b077aed3SPierre Pronchery { 509*b077aed3SPierre Pronchery X509_REQ *req = NULL; 510*b077aed3SPierre Pronchery BIO *in; 511*b077aed3SPierre Pronchery 512*b077aed3SPierre Pronchery if (format == FORMAT_UNDEF) 513*b077aed3SPierre Pronchery format = FORMAT_PEM; 514*b077aed3SPierre Pronchery if (desc == NULL) 515*b077aed3SPierre Pronchery desc = "CSR"; 516*b077aed3SPierre Pronchery in = bio_open_default(file, 'r', format); 517*b077aed3SPierre Pronchery if (in == NULL) 518*b077aed3SPierre Pronchery goto end; 519*b077aed3SPierre Pronchery 520*b077aed3SPierre Pronchery if (format == FORMAT_ASN1) 521*b077aed3SPierre Pronchery req = d2i_X509_REQ_bio(in, NULL); 522*b077aed3SPierre Pronchery else if (format == FORMAT_PEM) 523*b077aed3SPierre Pronchery req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 524*b077aed3SPierre Pronchery else 525*b077aed3SPierre Pronchery print_format_error(format, OPT_FMT_PEMDER); 526*b077aed3SPierre Pronchery 527*b077aed3SPierre Pronchery end: 528*b077aed3SPierre Pronchery if (req == NULL) { 529*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to load %s\n", desc); 530*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 531*b077aed3SPierre Pronchery } 532*b077aed3SPierre Pronchery BIO_free(in); 533*b077aed3SPierre Pronchery return req; 534*b077aed3SPierre Pronchery } 535*b077aed3SPierre Pronchery 536*b077aed3SPierre Pronchery void cleanse(char *str) 537*b077aed3SPierre Pronchery { 538*b077aed3SPierre Pronchery if (str != NULL) 539*b077aed3SPierre Pronchery OPENSSL_cleanse(str, strlen(str)); 540*b077aed3SPierre Pronchery } 541*b077aed3SPierre Pronchery 542*b077aed3SPierre Pronchery void clear_free(char *str) 543*b077aed3SPierre Pronchery { 544*b077aed3SPierre Pronchery if (str != NULL) 545*b077aed3SPierre Pronchery OPENSSL_clear_free(str, strlen(str)); 546*b077aed3SPierre Pronchery } 547*b077aed3SPierre Pronchery 548*b077aed3SPierre Pronchery EVP_PKEY *load_key(const char *uri, int format, int may_stdin, 549*b077aed3SPierre Pronchery const char *pass, ENGINE *e, const char *desc) 550*b077aed3SPierre Pronchery { 551*b077aed3SPierre Pronchery EVP_PKEY *pkey = NULL; 552*b077aed3SPierre Pronchery char *allocated_uri = NULL; 553*b077aed3SPierre Pronchery 554*b077aed3SPierre Pronchery if (desc == NULL) 555*b077aed3SPierre Pronchery desc = "private key"; 556*b077aed3SPierre Pronchery 557*b077aed3SPierre Pronchery if (format == FORMAT_ENGINE) { 558*b077aed3SPierre Pronchery uri = allocated_uri = make_engine_uri(e, uri, desc); 559*b077aed3SPierre Pronchery } 560*b077aed3SPierre Pronchery (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, 561*b077aed3SPierre Pronchery &pkey, NULL, NULL, NULL, NULL, NULL, NULL); 562*b077aed3SPierre Pronchery 563*b077aed3SPierre Pronchery OPENSSL_free(allocated_uri); 564*b077aed3SPierre Pronchery return pkey; 565*b077aed3SPierre Pronchery } 566*b077aed3SPierre Pronchery 567*b077aed3SPierre Pronchery EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, 568*b077aed3SPierre Pronchery const char *pass, ENGINE *e, const char *desc) 569*b077aed3SPierre Pronchery { 570*b077aed3SPierre Pronchery EVP_PKEY *pkey = NULL; 571*b077aed3SPierre Pronchery char *allocated_uri = NULL; 572*b077aed3SPierre Pronchery 573*b077aed3SPierre Pronchery if (desc == NULL) 574*b077aed3SPierre Pronchery desc = "public key"; 575*b077aed3SPierre Pronchery 576*b077aed3SPierre Pronchery if (format == FORMAT_ENGINE) { 577*b077aed3SPierre Pronchery uri = allocated_uri = make_engine_uri(e, uri, desc); 578*b077aed3SPierre Pronchery } 579*b077aed3SPierre Pronchery (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 580*b077aed3SPierre Pronchery NULL, &pkey, NULL, NULL, NULL, NULL, NULL); 581*b077aed3SPierre Pronchery 582*b077aed3SPierre Pronchery OPENSSL_free(allocated_uri); 583*b077aed3SPierre Pronchery return pkey; 584*b077aed3SPierre Pronchery } 585*b077aed3SPierre Pronchery 586*b077aed3SPierre Pronchery EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin, 587*b077aed3SPierre Pronchery const char *keytype, const char *desc, 588*b077aed3SPierre Pronchery int suppress_decode_errors) 589*b077aed3SPierre Pronchery { 590*b077aed3SPierre Pronchery EVP_PKEY *params = NULL; 591*b077aed3SPierre Pronchery 592*b077aed3SPierre Pronchery if (desc == NULL) 593*b077aed3SPierre Pronchery desc = "key parameters"; 594*b077aed3SPierre Pronchery 595*b077aed3SPierre Pronchery (void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc, 596*b077aed3SPierre Pronchery NULL, NULL, ¶ms, NULL, NULL, NULL, 597*b077aed3SPierre Pronchery NULL, suppress_decode_errors); 598*b077aed3SPierre Pronchery if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) { 599*b077aed3SPierre Pronchery if (!suppress_decode_errors) { 600*b077aed3SPierre Pronchery BIO_printf(bio_err, 601*b077aed3SPierre Pronchery "Unable to load %s from %s (unexpected parameters type)\n", 602*b077aed3SPierre Pronchery desc, uri); 603*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 604*b077aed3SPierre Pronchery } 605*b077aed3SPierre Pronchery EVP_PKEY_free(params); 606*b077aed3SPierre Pronchery params = NULL; 607*b077aed3SPierre Pronchery } 608*b077aed3SPierre Pronchery return params; 609*b077aed3SPierre Pronchery } 610*b077aed3SPierre Pronchery 611*b077aed3SPierre Pronchery EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin, 612*b077aed3SPierre Pronchery const char *keytype, const char *desc) 613*b077aed3SPierre Pronchery { 614*b077aed3SPierre Pronchery return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0); 615*b077aed3SPierre Pronchery } 616*b077aed3SPierre Pronchery 617*b077aed3SPierre Pronchery void app_bail_out(char *fmt, ...) 618*b077aed3SPierre Pronchery { 619*b077aed3SPierre Pronchery va_list args; 620*b077aed3SPierre Pronchery 621*b077aed3SPierre Pronchery va_start(args, fmt); 622*b077aed3SPierre Pronchery BIO_vprintf(bio_err, fmt, args); 623*b077aed3SPierre Pronchery va_end(args); 624*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 625*b077aed3SPierre Pronchery exit(EXIT_FAILURE); 626*b077aed3SPierre Pronchery } 627*b077aed3SPierre Pronchery 628*b077aed3SPierre Pronchery void *app_malloc(size_t sz, const char *what) 629*b077aed3SPierre Pronchery { 630*b077aed3SPierre Pronchery void *vp = OPENSSL_malloc(sz); 631*b077aed3SPierre Pronchery 632*b077aed3SPierre Pronchery if (vp == NULL) 633*b077aed3SPierre Pronchery app_bail_out("%s: Could not allocate %zu bytes for %s\n", 634*b077aed3SPierre Pronchery opt_getprog(), sz, what); 635*b077aed3SPierre Pronchery return vp; 636*b077aed3SPierre Pronchery } 637*b077aed3SPierre Pronchery 638*b077aed3SPierre Pronchery char *next_item(char *opt) /* in list separated by comma and/or space */ 639*b077aed3SPierre Pronchery { 640*b077aed3SPierre Pronchery /* advance to separator (comma or whitespace), if any */ 641*b077aed3SPierre Pronchery while (*opt != ',' && !isspace(*opt) && *opt != '\0') 642*b077aed3SPierre Pronchery opt++; 643*b077aed3SPierre Pronchery if (*opt != '\0') { 644*b077aed3SPierre Pronchery /* terminate current item */ 645*b077aed3SPierre Pronchery *opt++ = '\0'; 646*b077aed3SPierre Pronchery /* skip over any whitespace after separator */ 647*b077aed3SPierre Pronchery while (isspace(*opt)) 648*b077aed3SPierre Pronchery opt++; 649*b077aed3SPierre Pronchery } 650*b077aed3SPierre Pronchery return *opt == '\0' ? NULL : opt; /* NULL indicates end of input */ 651*b077aed3SPierre Pronchery } 652*b077aed3SPierre Pronchery 653*b077aed3SPierre Pronchery static void warn_cert_msg(const char *uri, X509 *cert, const char *msg) 654*b077aed3SPierre Pronchery { 655*b077aed3SPierre Pronchery char *subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); 656*b077aed3SPierre Pronchery 657*b077aed3SPierre Pronchery BIO_printf(bio_err, "Warning: certificate from '%s' with subject '%s' %s\n", 658*b077aed3SPierre Pronchery uri, subj, msg); 659*b077aed3SPierre Pronchery OPENSSL_free(subj); 660*b077aed3SPierre Pronchery } 661*b077aed3SPierre Pronchery 662*b077aed3SPierre Pronchery static void warn_cert(const char *uri, X509 *cert, int warn_EE, 663*b077aed3SPierre Pronchery X509_VERIFY_PARAM *vpm) 664*b077aed3SPierre Pronchery { 665*b077aed3SPierre Pronchery uint32_t ex_flags = X509_get_extension_flags(cert); 666*b077aed3SPierre Pronchery int res = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert), 667*b077aed3SPierre Pronchery X509_get0_notAfter(cert)); 668*b077aed3SPierre Pronchery 669*b077aed3SPierre Pronchery if (res != 0) 670*b077aed3SPierre Pronchery warn_cert_msg(uri, cert, res > 0 ? "has expired" : "not yet valid"); 671*b077aed3SPierre Pronchery if (warn_EE && (ex_flags & EXFLAG_V1) == 0 && (ex_flags & EXFLAG_CA) == 0) 672*b077aed3SPierre Pronchery warn_cert_msg(uri, cert, "is not a CA cert"); 673*b077aed3SPierre Pronchery } 674*b077aed3SPierre Pronchery 675*b077aed3SPierre Pronchery static void warn_certs(const char *uri, STACK_OF(X509) *certs, int warn_EE, 676*b077aed3SPierre Pronchery X509_VERIFY_PARAM *vpm) 677*b077aed3SPierre Pronchery { 678*b077aed3SPierre Pronchery int i; 679*b077aed3SPierre Pronchery 680*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_num(certs); i++) 681*b077aed3SPierre Pronchery warn_cert(uri, sk_X509_value(certs, i), warn_EE, vpm); 682*b077aed3SPierre Pronchery } 683*b077aed3SPierre Pronchery 684*b077aed3SPierre Pronchery int load_cert_certs(const char *uri, 685*b077aed3SPierre Pronchery X509 **pcert, STACK_OF(X509) **pcerts, 686*b077aed3SPierre Pronchery int exclude_http, const char *pass, const char *desc, 687*b077aed3SPierre Pronchery X509_VERIFY_PARAM *vpm) 688*b077aed3SPierre Pronchery { 689*b077aed3SPierre Pronchery int ret = 0; 690*b077aed3SPierre Pronchery char *pass_string; 691*b077aed3SPierre Pronchery 692*b077aed3SPierre Pronchery if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0 693*b077aed3SPierre Pronchery || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) { 694*b077aed3SPierre Pronchery BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc); 695*b077aed3SPierre Pronchery return ret; 696*b077aed3SPierre Pronchery } 697*b077aed3SPierre Pronchery pass_string = get_passwd(pass, desc); 698*b077aed3SPierre Pronchery ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, 699*b077aed3SPierre Pronchery NULL, NULL, NULL, 700*b077aed3SPierre Pronchery pcert, pcerts, NULL, NULL); 701*b077aed3SPierre Pronchery clear_free(pass_string); 702*b077aed3SPierre Pronchery 703*b077aed3SPierre Pronchery if (ret) { 704*b077aed3SPierre Pronchery if (pcert != NULL) 705*b077aed3SPierre Pronchery warn_cert(uri, *pcert, 0, vpm); 706*b077aed3SPierre Pronchery if (pcerts != NULL) 707*b077aed3SPierre Pronchery warn_certs(uri, *pcerts, 1, vpm); 708*b077aed3SPierre Pronchery } else { 709*b077aed3SPierre Pronchery if (pcerts != NULL) { 710*b077aed3SPierre Pronchery sk_X509_pop_free(*pcerts, X509_free); 711*b077aed3SPierre Pronchery *pcerts = NULL; 712*b077aed3SPierre Pronchery } 713*b077aed3SPierre Pronchery } 714*b077aed3SPierre Pronchery return ret; 715*b077aed3SPierre Pronchery } 716*b077aed3SPierre Pronchery 717*b077aed3SPierre Pronchery STACK_OF(X509) *load_certs_multifile(char *files, const char *pass, 718*b077aed3SPierre Pronchery const char *desc, X509_VERIFY_PARAM *vpm) 719*b077aed3SPierre Pronchery { 720*b077aed3SPierre Pronchery STACK_OF(X509) *certs = NULL; 721*b077aed3SPierre Pronchery STACK_OF(X509) *result = sk_X509_new_null(); 722*b077aed3SPierre Pronchery 723*b077aed3SPierre Pronchery if (files == NULL) 724*b077aed3SPierre Pronchery goto err; 725*b077aed3SPierre Pronchery if (result == NULL) 726*b077aed3SPierre Pronchery goto oom; 727*b077aed3SPierre Pronchery 728*b077aed3SPierre Pronchery while (files != NULL) { 729*b077aed3SPierre Pronchery char *next = next_item(files); 730*b077aed3SPierre Pronchery 731*b077aed3SPierre Pronchery if (!load_cert_certs(files, NULL, &certs, 0, pass, desc, vpm)) 732*b077aed3SPierre Pronchery goto err; 733*b077aed3SPierre Pronchery if (!X509_add_certs(result, certs, 734*b077aed3SPierre Pronchery X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP)) 735*b077aed3SPierre Pronchery goto oom; 736*b077aed3SPierre Pronchery sk_X509_pop_free(certs, X509_free); 737*b077aed3SPierre Pronchery certs = NULL; 738*b077aed3SPierre Pronchery files = next; 739*b077aed3SPierre Pronchery } 740*b077aed3SPierre Pronchery return result; 741*b077aed3SPierre Pronchery 742*b077aed3SPierre Pronchery oom: 743*b077aed3SPierre Pronchery BIO_printf(bio_err, "out of memory\n"); 744*b077aed3SPierre Pronchery err: 745*b077aed3SPierre Pronchery sk_X509_pop_free(certs, X509_free); 746*b077aed3SPierre Pronchery sk_X509_pop_free(result, X509_free); 747*b077aed3SPierre Pronchery return NULL; 748*b077aed3SPierre Pronchery } 749*b077aed3SPierre Pronchery 750*b077aed3SPierre Pronchery static X509_STORE *sk_X509_to_store(X509_STORE *store /* may be NULL */, 751*b077aed3SPierre Pronchery const STACK_OF(X509) *certs /* may NULL */) 752*b077aed3SPierre Pronchery { 753*b077aed3SPierre Pronchery int i; 754*b077aed3SPierre Pronchery 755*b077aed3SPierre Pronchery if (store == NULL) 756*b077aed3SPierre Pronchery store = X509_STORE_new(); 757*b077aed3SPierre Pronchery if (store == NULL) 758*b077aed3SPierre Pronchery return NULL; 759*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_num(certs); i++) { 760*b077aed3SPierre Pronchery if (!X509_STORE_add_cert(store, sk_X509_value(certs, i))) { 761*b077aed3SPierre Pronchery X509_STORE_free(store); 762*b077aed3SPierre Pronchery return NULL; 763*b077aed3SPierre Pronchery } 764*b077aed3SPierre Pronchery } 765*b077aed3SPierre Pronchery return store; 766*b077aed3SPierre Pronchery } 767*b077aed3SPierre Pronchery 768*b077aed3SPierre Pronchery /* 769*b077aed3SPierre Pronchery * Create cert store structure with certificates read from given file(s). 770*b077aed3SPierre Pronchery * Returns pointer to created X509_STORE on success, NULL on error. 771*b077aed3SPierre Pronchery */ 772*b077aed3SPierre Pronchery X509_STORE *load_certstore(char *input, const char *pass, const char *desc, 773*b077aed3SPierre Pronchery X509_VERIFY_PARAM *vpm) 774*b077aed3SPierre Pronchery { 775*b077aed3SPierre Pronchery X509_STORE *store = NULL; 776*b077aed3SPierre Pronchery STACK_OF(X509) *certs = NULL; 777*b077aed3SPierre Pronchery 778*b077aed3SPierre Pronchery while (input != NULL) { 779*b077aed3SPierre Pronchery char *next = next_item(input); 780*b077aed3SPierre Pronchery int ok; 781*b077aed3SPierre Pronchery 782*b077aed3SPierre Pronchery if (!load_cert_certs(input, NULL, &certs, 1, pass, desc, vpm)) { 783*b077aed3SPierre Pronchery X509_STORE_free(store); 784*b077aed3SPierre Pronchery return NULL; 785*b077aed3SPierre Pronchery } 786*b077aed3SPierre Pronchery ok = (store = sk_X509_to_store(store, certs)) != NULL; 787*b077aed3SPierre Pronchery sk_X509_pop_free(certs, X509_free); 788*b077aed3SPierre Pronchery certs = NULL; 789*b077aed3SPierre Pronchery if (!ok) 790*b077aed3SPierre Pronchery return NULL; 791*b077aed3SPierre Pronchery input = next; 792*b077aed3SPierre Pronchery } 793*b077aed3SPierre Pronchery return store; 794*b077aed3SPierre Pronchery } 795*b077aed3SPierre Pronchery 796*b077aed3SPierre Pronchery /* 797*b077aed3SPierre Pronchery * Initialize or extend, if *certs != NULL, a certificate stack. 798*b077aed3SPierre Pronchery * The caller is responsible for freeing *certs if its value is left not NULL. 799*b077aed3SPierre Pronchery */ 800*b077aed3SPierre Pronchery int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs, 801*b077aed3SPierre Pronchery const char *pass, const char *desc) 802*b077aed3SPierre Pronchery { 803*b077aed3SPierre Pronchery int was_NULL = *certs == NULL; 804*b077aed3SPierre Pronchery int ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, 805*b077aed3SPierre Pronchery pass, desc, NULL, NULL, 806*b077aed3SPierre Pronchery NULL, NULL, certs, NULL, NULL); 807*b077aed3SPierre Pronchery 808*b077aed3SPierre Pronchery if (!ret && was_NULL) { 809*b077aed3SPierre Pronchery sk_X509_pop_free(*certs, X509_free); 810*b077aed3SPierre Pronchery *certs = NULL; 811*b077aed3SPierre Pronchery } 812*b077aed3SPierre Pronchery return ret; 813*b077aed3SPierre Pronchery } 814*b077aed3SPierre Pronchery 815*b077aed3SPierre Pronchery /* 816*b077aed3SPierre Pronchery * Initialize or extend, if *crls != NULL, a certificate stack. 817*b077aed3SPierre Pronchery * The caller is responsible for freeing *crls if its value is left not NULL. 818*b077aed3SPierre Pronchery */ 819*b077aed3SPierre Pronchery int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, 820*b077aed3SPierre Pronchery const char *pass, const char *desc) 821*b077aed3SPierre Pronchery { 822*b077aed3SPierre Pronchery int was_NULL = *crls == NULL; 823*b077aed3SPierre Pronchery int ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, 824*b077aed3SPierre Pronchery NULL, NULL, NULL, 825*b077aed3SPierre Pronchery NULL, NULL, NULL, crls); 826*b077aed3SPierre Pronchery 827*b077aed3SPierre Pronchery if (!ret && was_NULL) { 828*b077aed3SPierre Pronchery sk_X509_CRL_pop_free(*crls, X509_CRL_free); 829*b077aed3SPierre Pronchery *crls = NULL; 830*b077aed3SPierre Pronchery } 831*b077aed3SPierre Pronchery return ret; 832*b077aed3SPierre Pronchery } 833*b077aed3SPierre Pronchery 834*b077aed3SPierre Pronchery static const char *format2string(int format) 835*b077aed3SPierre Pronchery { 836*b077aed3SPierre Pronchery switch(format) { 837*b077aed3SPierre Pronchery case FORMAT_PEM: 838*b077aed3SPierre Pronchery return "PEM"; 839*b077aed3SPierre Pronchery case FORMAT_ASN1: 840*b077aed3SPierre Pronchery return "DER"; 841*b077aed3SPierre Pronchery } 842*b077aed3SPierre Pronchery return NULL; 843*b077aed3SPierre Pronchery } 844*b077aed3SPierre Pronchery 845*b077aed3SPierre Pronchery /* Set type expectation, but clear it if objects of different types expected. */ 846*b077aed3SPierre Pronchery #define SET_EXPECT(expect, val) ((expect) = (expect) < 0 ? (val) : ((expect) == (val) ? (val) : 0)) 847*b077aed3SPierre Pronchery /* 848*b077aed3SPierre Pronchery * Load those types of credentials for which the result pointer is not NULL. 849*b077aed3SPierre Pronchery * Reads from stdio if uri is NULL and maybe_stdin is nonzero. 850*b077aed3SPierre Pronchery * For non-NULL ppkey, pcert, and pcrl the first suitable value found is loaded. 851*b077aed3SPierre Pronchery * If pcerts is non-NULL and *pcerts == NULL then a new cert list is allocated. 852*b077aed3SPierre Pronchery * If pcerts is non-NULL then all available certificates are appended to *pcerts 853*b077aed3SPierre Pronchery * except any certificate assigned to *pcert. 854*b077aed3SPierre Pronchery * If pcrls is non-NULL and *pcrls == NULL then a new list of CRLs is allocated. 855*b077aed3SPierre Pronchery * If pcrls is non-NULL then all available CRLs are appended to *pcerts 856*b077aed3SPierre Pronchery * except any CRL assigned to *pcrl. 857*b077aed3SPierre Pronchery * In any case (also on error) the caller is responsible for freeing all members 858*b077aed3SPierre Pronchery * of *pcerts and *pcrls (as far as they are not NULL). 859*b077aed3SPierre Pronchery */ 860*b077aed3SPierre Pronchery static 861*b077aed3SPierre Pronchery int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, 862*b077aed3SPierre Pronchery const char *pass, const char *desc, 863*b077aed3SPierre Pronchery EVP_PKEY **ppkey, EVP_PKEY **ppubkey, 864*b077aed3SPierre Pronchery EVP_PKEY **pparams, 865*b077aed3SPierre Pronchery X509 **pcert, STACK_OF(X509) **pcerts, 866*b077aed3SPierre Pronchery X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls, 867*b077aed3SPierre Pronchery int suppress_decode_errors) 868*b077aed3SPierre Pronchery { 869*b077aed3SPierre Pronchery PW_CB_DATA uidata; 870*b077aed3SPierre Pronchery OSSL_STORE_CTX *ctx = NULL; 871*b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx = app_get0_libctx(); 872*b077aed3SPierre Pronchery const char *propq = app_get0_propq(); 873*b077aed3SPierre Pronchery int ncerts = 0; 874*b077aed3SPierre Pronchery int ncrls = 0; 875*b077aed3SPierre Pronchery const char *failed = 876*b077aed3SPierre Pronchery ppkey != NULL ? "key" : ppubkey != NULL ? "public key" : 877*b077aed3SPierre Pronchery pparams != NULL ? "params" : pcert != NULL ? "cert" : 878*b077aed3SPierre Pronchery pcrl != NULL ? "CRL" : pcerts != NULL ? "certs" : 879*b077aed3SPierre Pronchery pcrls != NULL ? "CRLs" : NULL; 880*b077aed3SPierre Pronchery int cnt_expectations = 0; 881*b077aed3SPierre Pronchery int expect = -1; 882*b077aed3SPierre Pronchery const char *input_type; 883*b077aed3SPierre Pronchery OSSL_PARAM itp[2]; 884*b077aed3SPierre Pronchery const OSSL_PARAM *params = NULL; 885*b077aed3SPierre Pronchery 886*b077aed3SPierre Pronchery if (ppkey != NULL) { 887*b077aed3SPierre Pronchery *ppkey = NULL; 888*b077aed3SPierre Pronchery cnt_expectations++; 889*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_PKEY); 890*b077aed3SPierre Pronchery } 891*b077aed3SPierre Pronchery if (ppubkey != NULL) { 892*b077aed3SPierre Pronchery *ppubkey = NULL; 893*b077aed3SPierre Pronchery cnt_expectations++; 894*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_PUBKEY); 895*b077aed3SPierre Pronchery } 896*b077aed3SPierre Pronchery if (pparams != NULL) { 897*b077aed3SPierre Pronchery *pparams = NULL; 898*b077aed3SPierre Pronchery cnt_expectations++; 899*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_PARAMS); 900*b077aed3SPierre Pronchery } 901*b077aed3SPierre Pronchery if (pcert != NULL) { 902*b077aed3SPierre Pronchery *pcert = NULL; 903*b077aed3SPierre Pronchery cnt_expectations++; 904*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_CERT); 905*b077aed3SPierre Pronchery } 906*b077aed3SPierre Pronchery if (pcerts != NULL) { 907*b077aed3SPierre Pronchery if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) { 908*b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory loading"); 909*b077aed3SPierre Pronchery goto end; 910*b077aed3SPierre Pronchery } 911*b077aed3SPierre Pronchery cnt_expectations++; 912*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_CERT); 913*b077aed3SPierre Pronchery } 914*b077aed3SPierre Pronchery if (pcrl != NULL) { 915*b077aed3SPierre Pronchery *pcrl = NULL; 916*b077aed3SPierre Pronchery cnt_expectations++; 917*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_CRL); 918*b077aed3SPierre Pronchery } 919*b077aed3SPierre Pronchery if (pcrls != NULL) { 920*b077aed3SPierre Pronchery if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) { 921*b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory loading"); 922*b077aed3SPierre Pronchery goto end; 923*b077aed3SPierre Pronchery } 924*b077aed3SPierre Pronchery cnt_expectations++; 925*b077aed3SPierre Pronchery SET_EXPECT(expect, OSSL_STORE_INFO_CRL); 926*b077aed3SPierre Pronchery } 927*b077aed3SPierre Pronchery if (cnt_expectations == 0) { 928*b077aed3SPierre Pronchery BIO_printf(bio_err, "Internal error: nothing to load from %s\n", 929*b077aed3SPierre Pronchery uri != NULL ? uri : "<stdin>"); 930*b077aed3SPierre Pronchery return 0; 931*b077aed3SPierre Pronchery } 932*b077aed3SPierre Pronchery 933*b077aed3SPierre Pronchery uidata.password = pass; 934*b077aed3SPierre Pronchery uidata.prompt_info = uri; 935*b077aed3SPierre Pronchery 936*b077aed3SPierre Pronchery if ((input_type = format2string(format)) != NULL) { 937*b077aed3SPierre Pronchery itp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_INPUT_TYPE, 938*b077aed3SPierre Pronchery (char *)input_type, 0); 939*b077aed3SPierre Pronchery itp[1] = OSSL_PARAM_construct_end(); 940*b077aed3SPierre Pronchery params = itp; 941*b077aed3SPierre Pronchery } 942*b077aed3SPierre Pronchery 943*b077aed3SPierre Pronchery if (uri == NULL) { 944*b077aed3SPierre Pronchery BIO *bio; 945*b077aed3SPierre Pronchery 946*b077aed3SPierre Pronchery if (!maybe_stdin) { 947*b077aed3SPierre Pronchery BIO_printf(bio_err, "No filename or uri specified for loading"); 948*b077aed3SPierre Pronchery goto end; 949*b077aed3SPierre Pronchery } 950*b077aed3SPierre Pronchery uri = "<stdin>"; 951*b077aed3SPierre Pronchery unbuffer(stdin); 952*b077aed3SPierre Pronchery bio = BIO_new_fp(stdin, 0); 953*b077aed3SPierre Pronchery if (bio != NULL) { 954*b077aed3SPierre Pronchery ctx = OSSL_STORE_attach(bio, "file", libctx, propq, 955*b077aed3SPierre Pronchery get_ui_method(), &uidata, params, 956*b077aed3SPierre Pronchery NULL, NULL); 957*b077aed3SPierre Pronchery BIO_free(bio); 958*b077aed3SPierre Pronchery } 959*b077aed3SPierre Pronchery } else { 960*b077aed3SPierre Pronchery ctx = OSSL_STORE_open_ex(uri, libctx, propq, get_ui_method(), &uidata, 961*b077aed3SPierre Pronchery params, NULL, NULL); 962*b077aed3SPierre Pronchery } 963*b077aed3SPierre Pronchery if (ctx == NULL) { 964*b077aed3SPierre Pronchery BIO_printf(bio_err, "Could not open file or uri for loading"); 965*b077aed3SPierre Pronchery goto end; 966*b077aed3SPierre Pronchery } 967*b077aed3SPierre Pronchery if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) 968*b077aed3SPierre Pronchery goto end; 969*b077aed3SPierre Pronchery 970*b077aed3SPierre Pronchery failed = NULL; 971*b077aed3SPierre Pronchery while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) { 972*b077aed3SPierre Pronchery OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); 973*b077aed3SPierre Pronchery int type, ok = 1; 974*b077aed3SPierre Pronchery 975*b077aed3SPierre Pronchery /* 976*b077aed3SPierre Pronchery * This can happen (for example) if we attempt to load a file with 977*b077aed3SPierre Pronchery * multiple different types of things in it - but the thing we just 978*b077aed3SPierre Pronchery * tried to load wasn't one of the ones we wanted, e.g. if we're trying 979*b077aed3SPierre Pronchery * to load a certificate but the file has both the private key and the 980*b077aed3SPierre Pronchery * certificate in it. We just retry until eof. 981*b077aed3SPierre Pronchery */ 982*b077aed3SPierre Pronchery if (info == NULL) { 983*b077aed3SPierre Pronchery continue; 984*b077aed3SPierre Pronchery } 985*b077aed3SPierre Pronchery 986*b077aed3SPierre Pronchery type = OSSL_STORE_INFO_get_type(info); 987*b077aed3SPierre Pronchery switch (type) { 988*b077aed3SPierre Pronchery case OSSL_STORE_INFO_PKEY: 989*b077aed3SPierre Pronchery if (ppkey != NULL && *ppkey == NULL) { 990*b077aed3SPierre Pronchery ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL; 991*b077aed3SPierre Pronchery cnt_expectations -= ok; 992*b077aed3SPierre Pronchery } 993*b077aed3SPierre Pronchery /* 994*b077aed3SPierre Pronchery * An EVP_PKEY with private parts also holds the public parts, 995*b077aed3SPierre Pronchery * so if the caller asked for a public key, and we got a private 996*b077aed3SPierre Pronchery * key, we can still pass it back. 997*b077aed3SPierre Pronchery */ 998*b077aed3SPierre Pronchery if (ok && ppubkey != NULL && *ppubkey == NULL) { 999*b077aed3SPierre Pronchery ok = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL); 1000*b077aed3SPierre Pronchery cnt_expectations -= ok; 1001*b077aed3SPierre Pronchery } 1002*b077aed3SPierre Pronchery break; 1003*b077aed3SPierre Pronchery case OSSL_STORE_INFO_PUBKEY: 1004*b077aed3SPierre Pronchery if (ppubkey != NULL && *ppubkey == NULL) { 1005*b077aed3SPierre Pronchery ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL); 1006*b077aed3SPierre Pronchery cnt_expectations -= ok; 1007*b077aed3SPierre Pronchery } 1008*b077aed3SPierre Pronchery break; 1009*b077aed3SPierre Pronchery case OSSL_STORE_INFO_PARAMS: 1010*b077aed3SPierre Pronchery if (pparams != NULL && *pparams == NULL) { 1011*b077aed3SPierre Pronchery ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL); 1012*b077aed3SPierre Pronchery cnt_expectations -= ok; 1013*b077aed3SPierre Pronchery } 1014*b077aed3SPierre Pronchery break; 1015*b077aed3SPierre Pronchery case OSSL_STORE_INFO_CERT: 1016*b077aed3SPierre Pronchery if (pcert != NULL && *pcert == NULL) { 1017*b077aed3SPierre Pronchery ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL; 1018*b077aed3SPierre Pronchery cnt_expectations -= ok; 1019*b077aed3SPierre Pronchery } 1020*b077aed3SPierre Pronchery else if (pcerts != NULL) 1021*b077aed3SPierre Pronchery ok = X509_add_cert(*pcerts, 1022*b077aed3SPierre Pronchery OSSL_STORE_INFO_get1_CERT(info), 1023*b077aed3SPierre Pronchery X509_ADD_FLAG_DEFAULT); 1024*b077aed3SPierre Pronchery ncerts += ok; 1025*b077aed3SPierre Pronchery break; 1026*b077aed3SPierre Pronchery case OSSL_STORE_INFO_CRL: 1027*b077aed3SPierre Pronchery if (pcrl != NULL && *pcrl == NULL) { 1028*b077aed3SPierre Pronchery ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL; 1029*b077aed3SPierre Pronchery cnt_expectations -= ok; 1030*b077aed3SPierre Pronchery } 1031*b077aed3SPierre Pronchery else if (pcrls != NULL) 1032*b077aed3SPierre Pronchery ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info)); 1033*b077aed3SPierre Pronchery ncrls += ok; 1034*b077aed3SPierre Pronchery break; 1035*b077aed3SPierre Pronchery default: 1036*b077aed3SPierre Pronchery /* skip any other type */ 1037*b077aed3SPierre Pronchery break; 1038*b077aed3SPierre Pronchery } 1039*b077aed3SPierre Pronchery OSSL_STORE_INFO_free(info); 1040*b077aed3SPierre Pronchery if (!ok) { 1041*b077aed3SPierre Pronchery failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); 1042*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error reading"); 1043*b077aed3SPierre Pronchery break; 1044*b077aed3SPierre Pronchery } 1045*b077aed3SPierre Pronchery } 1046*b077aed3SPierre Pronchery 1047*b077aed3SPierre Pronchery end: 1048*b077aed3SPierre Pronchery OSSL_STORE_close(ctx); 1049*b077aed3SPierre Pronchery if (failed == NULL) { 1050*b077aed3SPierre Pronchery int any = 0; 1051*b077aed3SPierre Pronchery 1052*b077aed3SPierre Pronchery if ((ppkey != NULL && *ppkey == NULL) 1053*b077aed3SPierre Pronchery || (ppubkey != NULL && *ppubkey == NULL)) { 1054*b077aed3SPierre Pronchery failed = "key"; 1055*b077aed3SPierre Pronchery } else if (pparams != NULL && *pparams == NULL) { 1056*b077aed3SPierre Pronchery failed = "params"; 1057*b077aed3SPierre Pronchery } else if ((pcert != NULL || pcerts != NULL) && ncerts == 0) { 1058*b077aed3SPierre Pronchery if (pcert == NULL) 1059*b077aed3SPierre Pronchery any = 1; 1060*b077aed3SPierre Pronchery failed = "cert"; 1061*b077aed3SPierre Pronchery } else if ((pcrl != NULL || pcrls != NULL) && ncrls == 0) { 1062*b077aed3SPierre Pronchery if (pcrl == NULL) 1063*b077aed3SPierre Pronchery any = 1; 1064*b077aed3SPierre Pronchery failed = "CRL"; 1065*b077aed3SPierre Pronchery } 1066*b077aed3SPierre Pronchery if (!suppress_decode_errors) { 1067*b077aed3SPierre Pronchery if (failed != NULL) 1068*b077aed3SPierre Pronchery BIO_printf(bio_err, "Could not read"); 1069*b077aed3SPierre Pronchery if (any) 1070*b077aed3SPierre Pronchery BIO_printf(bio_err, " any"); 1071*b077aed3SPierre Pronchery } 1072*b077aed3SPierre Pronchery } 1073*b077aed3SPierre Pronchery if (!suppress_decode_errors && failed != NULL) { 1074*b077aed3SPierre Pronchery if (desc != NULL && strstr(desc, failed) != NULL) { 1075*b077aed3SPierre Pronchery BIO_printf(bio_err, " %s", desc); 1076*b077aed3SPierre Pronchery } else { 1077*b077aed3SPierre Pronchery BIO_printf(bio_err, " %s", failed); 1078*b077aed3SPierre Pronchery if (desc != NULL) 1079*b077aed3SPierre Pronchery BIO_printf(bio_err, " of %s", desc); 1080*b077aed3SPierre Pronchery } 1081*b077aed3SPierre Pronchery if (uri != NULL) 1082*b077aed3SPierre Pronchery BIO_printf(bio_err, " from %s", uri); 1083*b077aed3SPierre Pronchery BIO_printf(bio_err, "\n"); 1084*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1085*b077aed3SPierre Pronchery } 1086*b077aed3SPierre Pronchery if (suppress_decode_errors || failed == NULL) 1087*b077aed3SPierre Pronchery /* clear any spurious errors */ 1088*b077aed3SPierre Pronchery ERR_clear_error(); 1089*b077aed3SPierre Pronchery return failed == NULL; 1090*b077aed3SPierre Pronchery } 1091*b077aed3SPierre Pronchery 1092*b077aed3SPierre Pronchery int load_key_certs_crls(const char *uri, int format, int maybe_stdin, 1093*b077aed3SPierre Pronchery const char *pass, const char *desc, 1094*b077aed3SPierre Pronchery EVP_PKEY **ppkey, EVP_PKEY **ppubkey, 1095*b077aed3SPierre Pronchery EVP_PKEY **pparams, 1096*b077aed3SPierre Pronchery X509 **pcert, STACK_OF(X509) **pcerts, 1097*b077aed3SPierre Pronchery X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls) 1098*b077aed3SPierre Pronchery { 1099*b077aed3SPierre Pronchery return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc, 1100*b077aed3SPierre Pronchery ppkey, ppubkey, pparams, pcert, pcerts, 1101*b077aed3SPierre Pronchery pcrl, pcrls, 0); 1102*b077aed3SPierre Pronchery } 1103*b077aed3SPierre Pronchery 1104*b077aed3SPierre Pronchery #define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) 1105*b077aed3SPierre Pronchery /* Return error for unknown extensions */ 1106*b077aed3SPierre Pronchery #define X509V3_EXT_DEFAULT 0 1107*b077aed3SPierre Pronchery /* Print error for unknown extensions */ 1108*b077aed3SPierre Pronchery #define X509V3_EXT_ERROR_UNKNOWN (1L << 16) 1109*b077aed3SPierre Pronchery /* ASN1 parse unknown extensions */ 1110*b077aed3SPierre Pronchery #define X509V3_EXT_PARSE_UNKNOWN (2L << 16) 1111*b077aed3SPierre Pronchery /* BIO_dump unknown extensions */ 1112*b077aed3SPierre Pronchery #define X509V3_EXT_DUMP_UNKNOWN (3L << 16) 1113*b077aed3SPierre Pronchery 1114*b077aed3SPierre Pronchery #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ 1115*b077aed3SPierre Pronchery X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) 1116*b077aed3SPierre Pronchery 1117*b077aed3SPierre Pronchery int set_cert_ex(unsigned long *flags, const char *arg) 1118*b077aed3SPierre Pronchery { 1119*b077aed3SPierre Pronchery static const NAME_EX_TBL cert_tbl[] = { 1120*b077aed3SPierre Pronchery {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, 1121*b077aed3SPierre Pronchery {"ca_default", X509_FLAG_CA, 0xffffffffl}, 1122*b077aed3SPierre Pronchery {"no_header", X509_FLAG_NO_HEADER, 0}, 1123*b077aed3SPierre Pronchery {"no_version", X509_FLAG_NO_VERSION, 0}, 1124*b077aed3SPierre Pronchery {"no_serial", X509_FLAG_NO_SERIAL, 0}, 1125*b077aed3SPierre Pronchery {"no_signame", X509_FLAG_NO_SIGNAME, 0}, 1126*b077aed3SPierre Pronchery {"no_validity", X509_FLAG_NO_VALIDITY, 0}, 1127*b077aed3SPierre Pronchery {"no_subject", X509_FLAG_NO_SUBJECT, 0}, 1128*b077aed3SPierre Pronchery {"no_issuer", X509_FLAG_NO_ISSUER, 0}, 1129*b077aed3SPierre Pronchery {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, 1130*b077aed3SPierre Pronchery {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, 1131*b077aed3SPierre Pronchery {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, 1132*b077aed3SPierre Pronchery {"no_aux", X509_FLAG_NO_AUX, 0}, 1133*b077aed3SPierre Pronchery {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, 1134*b077aed3SPierre Pronchery {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, 1135*b077aed3SPierre Pronchery {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1136*b077aed3SPierre Pronchery {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1137*b077aed3SPierre Pronchery {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1138*b077aed3SPierre Pronchery {NULL, 0, 0} 1139*b077aed3SPierre Pronchery }; 1140*b077aed3SPierre Pronchery return set_multi_opts(flags, arg, cert_tbl); 1141*b077aed3SPierre Pronchery } 1142*b077aed3SPierre Pronchery 1143*b077aed3SPierre Pronchery int set_name_ex(unsigned long *flags, const char *arg) 1144*b077aed3SPierre Pronchery { 1145*b077aed3SPierre Pronchery static const NAME_EX_TBL ex_tbl[] = { 1146*b077aed3SPierre Pronchery {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, 1147*b077aed3SPierre Pronchery {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, 1148*b077aed3SPierre Pronchery {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, 1149*b077aed3SPierre Pronchery {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, 1150*b077aed3SPierre Pronchery {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, 1151*b077aed3SPierre Pronchery {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, 1152*b077aed3SPierre Pronchery {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, 1153*b077aed3SPierre Pronchery {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, 1154*b077aed3SPierre Pronchery {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, 1155*b077aed3SPierre Pronchery {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, 1156*b077aed3SPierre Pronchery {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, 1157*b077aed3SPierre Pronchery {"compat", XN_FLAG_COMPAT, 0xffffffffL}, 1158*b077aed3SPierre Pronchery {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, 1159*b077aed3SPierre Pronchery {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, 1160*b077aed3SPierre Pronchery {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, 1161*b077aed3SPierre Pronchery {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, 1162*b077aed3SPierre Pronchery {"dn_rev", XN_FLAG_DN_REV, 0}, 1163*b077aed3SPierre Pronchery {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, 1164*b077aed3SPierre Pronchery {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, 1165*b077aed3SPierre Pronchery {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, 1166*b077aed3SPierre Pronchery {"align", XN_FLAG_FN_ALIGN, 0}, 1167*b077aed3SPierre Pronchery {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, 1168*b077aed3SPierre Pronchery {"space_eq", XN_FLAG_SPC_EQ, 0}, 1169*b077aed3SPierre Pronchery {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, 1170*b077aed3SPierre Pronchery {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, 1171*b077aed3SPierre Pronchery {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, 1172*b077aed3SPierre Pronchery {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, 1173*b077aed3SPierre Pronchery {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, 1174*b077aed3SPierre Pronchery {NULL, 0, 0} 1175*b077aed3SPierre Pronchery }; 1176*b077aed3SPierre Pronchery if (set_multi_opts(flags, arg, ex_tbl) == 0) 1177*b077aed3SPierre Pronchery return 0; 1178*b077aed3SPierre Pronchery if (*flags != XN_FLAG_COMPAT 1179*b077aed3SPierre Pronchery && (*flags & XN_FLAG_SEP_MASK) == 0) 1180*b077aed3SPierre Pronchery *flags |= XN_FLAG_SEP_CPLUS_SPC; 1181*b077aed3SPierre Pronchery return 1; 1182*b077aed3SPierre Pronchery } 1183*b077aed3SPierre Pronchery 1184*b077aed3SPierre Pronchery int set_dateopt(unsigned long *dateopt, const char *arg) 1185*b077aed3SPierre Pronchery { 1186*b077aed3SPierre Pronchery if (OPENSSL_strcasecmp(arg, "rfc_822") == 0) 1187*b077aed3SPierre Pronchery *dateopt = ASN1_DTFLGS_RFC822; 1188*b077aed3SPierre Pronchery else if (OPENSSL_strcasecmp(arg, "iso_8601") == 0) 1189*b077aed3SPierre Pronchery *dateopt = ASN1_DTFLGS_ISO8601; 1190*b077aed3SPierre Pronchery else 1191*b077aed3SPierre Pronchery return 0; 1192*b077aed3SPierre Pronchery return 1; 1193*b077aed3SPierre Pronchery } 1194*b077aed3SPierre Pronchery 1195*b077aed3SPierre Pronchery int set_ext_copy(int *copy_type, const char *arg) 1196*b077aed3SPierre Pronchery { 1197*b077aed3SPierre Pronchery if (OPENSSL_strcasecmp(arg, "none") == 0) 1198*b077aed3SPierre Pronchery *copy_type = EXT_COPY_NONE; 1199*b077aed3SPierre Pronchery else if (OPENSSL_strcasecmp(arg, "copy") == 0) 1200*b077aed3SPierre Pronchery *copy_type = EXT_COPY_ADD; 1201*b077aed3SPierre Pronchery else if (OPENSSL_strcasecmp(arg, "copyall") == 0) 1202*b077aed3SPierre Pronchery *copy_type = EXT_COPY_ALL; 1203*b077aed3SPierre Pronchery else 1204*b077aed3SPierre Pronchery return 0; 1205*b077aed3SPierre Pronchery return 1; 1206*b077aed3SPierre Pronchery } 1207*b077aed3SPierre Pronchery 1208*b077aed3SPierre Pronchery int copy_extensions(X509 *x, X509_REQ *req, int copy_type) 1209*b077aed3SPierre Pronchery { 1210*b077aed3SPierre Pronchery STACK_OF(X509_EXTENSION) *exts; 1211*b077aed3SPierre Pronchery int i, ret = 0; 1212*b077aed3SPierre Pronchery 1213*b077aed3SPierre Pronchery if (x == NULL || req == NULL) 1214*b077aed3SPierre Pronchery return 0; 1215*b077aed3SPierre Pronchery if (copy_type == EXT_COPY_NONE) 1216*b077aed3SPierre Pronchery return 1; 1217*b077aed3SPierre Pronchery exts = X509_REQ_get_extensions(req); 1218*b077aed3SPierre Pronchery 1219*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 1220*b077aed3SPierre Pronchery X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); 1221*b077aed3SPierre Pronchery ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); 1222*b077aed3SPierre Pronchery int idx = X509_get_ext_by_OBJ(x, obj, -1); 1223*b077aed3SPierre Pronchery 1224*b077aed3SPierre Pronchery /* Does extension exist in target? */ 1225*b077aed3SPierre Pronchery if (idx != -1) { 1226*b077aed3SPierre Pronchery /* If normal copy don't override existing extension */ 1227*b077aed3SPierre Pronchery if (copy_type == EXT_COPY_ADD) 1228*b077aed3SPierre Pronchery continue; 1229*b077aed3SPierre Pronchery /* Delete all extensions of same type */ 1230*b077aed3SPierre Pronchery do { 1231*b077aed3SPierre Pronchery X509_EXTENSION_free(X509_delete_ext(x, idx)); 1232*b077aed3SPierre Pronchery idx = X509_get_ext_by_OBJ(x, obj, -1); 1233*b077aed3SPierre Pronchery } while (idx != -1); 1234*b077aed3SPierre Pronchery } 1235*b077aed3SPierre Pronchery if (!X509_add_ext(x, ext, -1)) 1236*b077aed3SPierre Pronchery goto end; 1237*b077aed3SPierre Pronchery } 1238*b077aed3SPierre Pronchery ret = 1; 1239*b077aed3SPierre Pronchery 1240*b077aed3SPierre Pronchery end: 1241*b077aed3SPierre Pronchery sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 1242*b077aed3SPierre Pronchery return ret; 1243*b077aed3SPierre Pronchery } 1244*b077aed3SPierre Pronchery 1245*b077aed3SPierre Pronchery static int set_multi_opts(unsigned long *flags, const char *arg, 1246*b077aed3SPierre Pronchery const NAME_EX_TBL * in_tbl) 1247*b077aed3SPierre Pronchery { 1248*b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *vals; 1249*b077aed3SPierre Pronchery CONF_VALUE *val; 1250*b077aed3SPierre Pronchery int i, ret = 1; 1251*b077aed3SPierre Pronchery if (!arg) 1252*b077aed3SPierre Pronchery return 0; 1253*b077aed3SPierre Pronchery vals = X509V3_parse_list(arg); 1254*b077aed3SPierre Pronchery for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 1255*b077aed3SPierre Pronchery val = sk_CONF_VALUE_value(vals, i); 1256*b077aed3SPierre Pronchery if (!set_table_opts(flags, val->name, in_tbl)) 1257*b077aed3SPierre Pronchery ret = 0; 1258*b077aed3SPierre Pronchery } 1259*b077aed3SPierre Pronchery sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 1260*b077aed3SPierre Pronchery return ret; 1261*b077aed3SPierre Pronchery } 1262*b077aed3SPierre Pronchery 1263*b077aed3SPierre Pronchery static int set_table_opts(unsigned long *flags, const char *arg, 1264*b077aed3SPierre Pronchery const NAME_EX_TBL * in_tbl) 1265*b077aed3SPierre Pronchery { 1266*b077aed3SPierre Pronchery char c; 1267*b077aed3SPierre Pronchery const NAME_EX_TBL *ptbl; 1268*b077aed3SPierre Pronchery c = arg[0]; 1269*b077aed3SPierre Pronchery 1270*b077aed3SPierre Pronchery if (c == '-') { 1271*b077aed3SPierre Pronchery c = 0; 1272*b077aed3SPierre Pronchery arg++; 1273*b077aed3SPierre Pronchery } else if (c == '+') { 1274*b077aed3SPierre Pronchery c = 1; 1275*b077aed3SPierre Pronchery arg++; 1276*b077aed3SPierre Pronchery } else { 1277*b077aed3SPierre Pronchery c = 1; 1278*b077aed3SPierre Pronchery } 1279*b077aed3SPierre Pronchery 1280*b077aed3SPierre Pronchery for (ptbl = in_tbl; ptbl->name; ptbl++) { 1281*b077aed3SPierre Pronchery if (OPENSSL_strcasecmp(arg, ptbl->name) == 0) { 1282*b077aed3SPierre Pronchery *flags &= ~ptbl->mask; 1283*b077aed3SPierre Pronchery if (c) 1284*b077aed3SPierre Pronchery *flags |= ptbl->flag; 1285*b077aed3SPierre Pronchery else 1286*b077aed3SPierre Pronchery *flags &= ~ptbl->flag; 1287*b077aed3SPierre Pronchery return 1; 1288*b077aed3SPierre Pronchery } 1289*b077aed3SPierre Pronchery } 1290*b077aed3SPierre Pronchery return 0; 1291*b077aed3SPierre Pronchery } 1292*b077aed3SPierre Pronchery 1293*b077aed3SPierre Pronchery void print_name(BIO *out, const char *title, const X509_NAME *nm) 1294*b077aed3SPierre Pronchery { 1295*b077aed3SPierre Pronchery char *buf; 1296*b077aed3SPierre Pronchery char mline = 0; 1297*b077aed3SPierre Pronchery int indent = 0; 1298*b077aed3SPierre Pronchery unsigned long lflags = get_nameopt(); 1299*b077aed3SPierre Pronchery 1300*b077aed3SPierre Pronchery if (out == NULL) 1301*b077aed3SPierre Pronchery return; 1302*b077aed3SPierre Pronchery if (title != NULL) 1303*b077aed3SPierre Pronchery BIO_puts(out, title); 1304*b077aed3SPierre Pronchery if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { 1305*b077aed3SPierre Pronchery mline = 1; 1306*b077aed3SPierre Pronchery indent = 4; 1307*b077aed3SPierre Pronchery } 1308*b077aed3SPierre Pronchery if (lflags == XN_FLAG_COMPAT) { 1309*b077aed3SPierre Pronchery buf = X509_NAME_oneline(nm, 0, 0); 1310*b077aed3SPierre Pronchery BIO_puts(out, buf); 1311*b077aed3SPierre Pronchery BIO_puts(out, "\n"); 1312*b077aed3SPierre Pronchery OPENSSL_free(buf); 1313*b077aed3SPierre Pronchery } else { 1314*b077aed3SPierre Pronchery if (mline) 1315*b077aed3SPierre Pronchery BIO_puts(out, "\n"); 1316*b077aed3SPierre Pronchery X509_NAME_print_ex(out, nm, indent, lflags); 1317*b077aed3SPierre Pronchery BIO_puts(out, "\n"); 1318*b077aed3SPierre Pronchery } 1319*b077aed3SPierre Pronchery } 1320*b077aed3SPierre Pronchery 1321*b077aed3SPierre Pronchery void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, 1322*b077aed3SPierre Pronchery int len, unsigned char *buffer) 1323*b077aed3SPierre Pronchery { 1324*b077aed3SPierre Pronchery BIO_printf(out, " static unsigned char %s_%d[] = {", var, len); 1325*b077aed3SPierre Pronchery if (BN_is_zero(in)) { 1326*b077aed3SPierre Pronchery BIO_printf(out, "\n 0x00"); 1327*b077aed3SPierre Pronchery } else { 1328*b077aed3SPierre Pronchery int i, l; 1329*b077aed3SPierre Pronchery 1330*b077aed3SPierre Pronchery l = BN_bn2bin(in, buffer); 1331*b077aed3SPierre Pronchery for (i = 0; i < l; i++) { 1332*b077aed3SPierre Pronchery BIO_printf(out, (i % 10) == 0 ? "\n " : " "); 1333*b077aed3SPierre Pronchery if (i < l - 1) 1334*b077aed3SPierre Pronchery BIO_printf(out, "0x%02X,", buffer[i]); 1335*b077aed3SPierre Pronchery else 1336*b077aed3SPierre Pronchery BIO_printf(out, "0x%02X", buffer[i]); 1337*b077aed3SPierre Pronchery } 1338*b077aed3SPierre Pronchery } 1339*b077aed3SPierre Pronchery BIO_printf(out, "\n };\n"); 1340*b077aed3SPierre Pronchery } 1341*b077aed3SPierre Pronchery 1342*b077aed3SPierre Pronchery void print_array(BIO *out, const char* title, int len, const unsigned char* d) 1343*b077aed3SPierre Pronchery { 1344*b077aed3SPierre Pronchery int i; 1345*b077aed3SPierre Pronchery 1346*b077aed3SPierre Pronchery BIO_printf(out, "unsigned char %s[%d] = {", title, len); 1347*b077aed3SPierre Pronchery for (i = 0; i < len; i++) { 1348*b077aed3SPierre Pronchery if ((i % 10) == 0) 1349*b077aed3SPierre Pronchery BIO_printf(out, "\n "); 1350*b077aed3SPierre Pronchery if (i < len - 1) 1351*b077aed3SPierre Pronchery BIO_printf(out, "0x%02X, ", d[i]); 1352*b077aed3SPierre Pronchery else 1353*b077aed3SPierre Pronchery BIO_printf(out, "0x%02X", d[i]); 1354*b077aed3SPierre Pronchery } 1355*b077aed3SPierre Pronchery BIO_printf(out, "\n};\n"); 1356*b077aed3SPierre Pronchery } 1357*b077aed3SPierre Pronchery 1358*b077aed3SPierre Pronchery X509_STORE *setup_verify(const char *CAfile, int noCAfile, 1359*b077aed3SPierre Pronchery const char *CApath, int noCApath, 1360*b077aed3SPierre Pronchery const char *CAstore, int noCAstore) 1361*b077aed3SPierre Pronchery { 1362*b077aed3SPierre Pronchery X509_STORE *store = X509_STORE_new(); 1363*b077aed3SPierre Pronchery X509_LOOKUP *lookup; 1364*b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx = app_get0_libctx(); 1365*b077aed3SPierre Pronchery const char *propq = app_get0_propq(); 1366*b077aed3SPierre Pronchery 1367*b077aed3SPierre Pronchery if (store == NULL) 1368*b077aed3SPierre Pronchery goto end; 1369*b077aed3SPierre Pronchery 1370*b077aed3SPierre Pronchery if (CAfile != NULL || !noCAfile) { 1371*b077aed3SPierre Pronchery lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 1372*b077aed3SPierre Pronchery if (lookup == NULL) 1373*b077aed3SPierre Pronchery goto end; 1374*b077aed3SPierre Pronchery if (CAfile != NULL) { 1375*b077aed3SPierre Pronchery if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, 1376*b077aed3SPierre Pronchery libctx, propq) <= 0) { 1377*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error loading file %s\n", CAfile); 1378*b077aed3SPierre Pronchery goto end; 1379*b077aed3SPierre Pronchery } 1380*b077aed3SPierre Pronchery } else { 1381*b077aed3SPierre Pronchery X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT, 1382*b077aed3SPierre Pronchery libctx, propq); 1383*b077aed3SPierre Pronchery } 1384*b077aed3SPierre Pronchery } 1385*b077aed3SPierre Pronchery 1386*b077aed3SPierre Pronchery if (CApath != NULL || !noCApath) { 1387*b077aed3SPierre Pronchery lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); 1388*b077aed3SPierre Pronchery if (lookup == NULL) 1389*b077aed3SPierre Pronchery goto end; 1390*b077aed3SPierre Pronchery if (CApath != NULL) { 1391*b077aed3SPierre Pronchery if (X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM) <= 0) { 1392*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error loading directory %s\n", CApath); 1393*b077aed3SPierre Pronchery goto end; 1394*b077aed3SPierre Pronchery } 1395*b077aed3SPierre Pronchery } else { 1396*b077aed3SPierre Pronchery X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); 1397*b077aed3SPierre Pronchery } 1398*b077aed3SPierre Pronchery } 1399*b077aed3SPierre Pronchery 1400*b077aed3SPierre Pronchery if (CAstore != NULL || !noCAstore) { 1401*b077aed3SPierre Pronchery lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store()); 1402*b077aed3SPierre Pronchery if (lookup == NULL) 1403*b077aed3SPierre Pronchery goto end; 1404*b077aed3SPierre Pronchery if (!X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq)) { 1405*b077aed3SPierre Pronchery if (CAstore != NULL) 1406*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error loading store URI %s\n", CAstore); 1407*b077aed3SPierre Pronchery goto end; 1408*b077aed3SPierre Pronchery } 1409*b077aed3SPierre Pronchery } 1410*b077aed3SPierre Pronchery 1411*b077aed3SPierre Pronchery ERR_clear_error(); 1412*b077aed3SPierre Pronchery return store; 1413*b077aed3SPierre Pronchery end: 1414*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1415*b077aed3SPierre Pronchery X509_STORE_free(store); 1416*b077aed3SPierre Pronchery return NULL; 1417*b077aed3SPierre Pronchery } 1418*b077aed3SPierre Pronchery 1419*b077aed3SPierre Pronchery static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) 1420*b077aed3SPierre Pronchery { 1421*b077aed3SPierre Pronchery const char *n; 1422*b077aed3SPierre Pronchery 1423*b077aed3SPierre Pronchery n = a[DB_serial]; 1424*b077aed3SPierre Pronchery while (*n == '0') 1425*b077aed3SPierre Pronchery n++; 1426*b077aed3SPierre Pronchery return OPENSSL_LH_strhash(n); 1427*b077aed3SPierre Pronchery } 1428*b077aed3SPierre Pronchery 1429*b077aed3SPierre Pronchery static int index_serial_cmp(const OPENSSL_CSTRING *a, 1430*b077aed3SPierre Pronchery const OPENSSL_CSTRING *b) 1431*b077aed3SPierre Pronchery { 1432*b077aed3SPierre Pronchery const char *aa, *bb; 1433*b077aed3SPierre Pronchery 1434*b077aed3SPierre Pronchery for (aa = a[DB_serial]; *aa == '0'; aa++) ; 1435*b077aed3SPierre Pronchery for (bb = b[DB_serial]; *bb == '0'; bb++) ; 1436*b077aed3SPierre Pronchery return strcmp(aa, bb); 1437*b077aed3SPierre Pronchery } 1438*b077aed3SPierre Pronchery 1439*b077aed3SPierre Pronchery static int index_name_qual(char **a) 1440*b077aed3SPierre Pronchery { 1441*b077aed3SPierre Pronchery return (a[0][0] == 'V'); 1442*b077aed3SPierre Pronchery } 1443*b077aed3SPierre Pronchery 1444*b077aed3SPierre Pronchery static unsigned long index_name_hash(const OPENSSL_CSTRING *a) 1445*b077aed3SPierre Pronchery { 1446*b077aed3SPierre Pronchery return OPENSSL_LH_strhash(a[DB_name]); 1447*b077aed3SPierre Pronchery } 1448*b077aed3SPierre Pronchery 1449*b077aed3SPierre Pronchery int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1450*b077aed3SPierre Pronchery { 1451*b077aed3SPierre Pronchery return strcmp(a[DB_name], b[DB_name]); 1452*b077aed3SPierre Pronchery } 1453*b077aed3SPierre Pronchery 1454*b077aed3SPierre Pronchery static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) 1455*b077aed3SPierre Pronchery static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) 1456*b077aed3SPierre Pronchery static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) 1457*b077aed3SPierre Pronchery static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) 1458*b077aed3SPierre Pronchery #undef BSIZE 1459*b077aed3SPierre Pronchery #define BSIZE 256 1460*b077aed3SPierre Pronchery BIGNUM *load_serial(const char *serialfile, int *exists, int create, 1461*b077aed3SPierre Pronchery ASN1_INTEGER **retai) 1462*b077aed3SPierre Pronchery { 1463*b077aed3SPierre Pronchery BIO *in = NULL; 1464*b077aed3SPierre Pronchery BIGNUM *ret = NULL; 1465*b077aed3SPierre Pronchery char buf[1024]; 1466*b077aed3SPierre Pronchery ASN1_INTEGER *ai = NULL; 1467*b077aed3SPierre Pronchery 1468*b077aed3SPierre Pronchery ai = ASN1_INTEGER_new(); 1469*b077aed3SPierre Pronchery if (ai == NULL) 1470*b077aed3SPierre Pronchery goto err; 1471*b077aed3SPierre Pronchery 1472*b077aed3SPierre Pronchery in = BIO_new_file(serialfile, "r"); 1473*b077aed3SPierre Pronchery if (exists != NULL) 1474*b077aed3SPierre Pronchery *exists = in != NULL; 1475*b077aed3SPierre Pronchery if (in == NULL) { 1476*b077aed3SPierre Pronchery if (!create) { 1477*b077aed3SPierre Pronchery perror(serialfile); 1478*b077aed3SPierre Pronchery goto err; 1479*b077aed3SPierre Pronchery } 1480*b077aed3SPierre Pronchery ERR_clear_error(); 1481*b077aed3SPierre Pronchery ret = BN_new(); 1482*b077aed3SPierre Pronchery if (ret == NULL) { 1483*b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory\n"); 1484*b077aed3SPierre Pronchery } else if (!rand_serial(ret, ai)) { 1485*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error creating random number to store in %s\n", 1486*b077aed3SPierre Pronchery serialfile); 1487*b077aed3SPierre Pronchery BN_free(ret); 1488*b077aed3SPierre Pronchery ret = NULL; 1489*b077aed3SPierre Pronchery } 1490*b077aed3SPierre Pronchery } else { 1491*b077aed3SPierre Pronchery if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { 1492*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to load number from %s\n", 1493*b077aed3SPierre Pronchery serialfile); 1494*b077aed3SPierre Pronchery goto err; 1495*b077aed3SPierre Pronchery } 1496*b077aed3SPierre Pronchery ret = ASN1_INTEGER_to_BN(ai, NULL); 1497*b077aed3SPierre Pronchery if (ret == NULL) { 1498*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error converting number from bin to BIGNUM\n"); 1499*b077aed3SPierre Pronchery goto err; 1500*b077aed3SPierre Pronchery } 1501*b077aed3SPierre Pronchery } 1502*b077aed3SPierre Pronchery 1503*b077aed3SPierre Pronchery if (ret != NULL && retai != NULL) { 1504*b077aed3SPierre Pronchery *retai = ai; 1505*b077aed3SPierre Pronchery ai = NULL; 1506*b077aed3SPierre Pronchery } 1507*b077aed3SPierre Pronchery err: 1508*b077aed3SPierre Pronchery if (ret == NULL) 1509*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1510*b077aed3SPierre Pronchery BIO_free(in); 1511*b077aed3SPierre Pronchery ASN1_INTEGER_free(ai); 1512*b077aed3SPierre Pronchery return ret; 1513*b077aed3SPierre Pronchery } 1514*b077aed3SPierre Pronchery 1515*b077aed3SPierre Pronchery int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, 1516*b077aed3SPierre Pronchery ASN1_INTEGER **retai) 1517*b077aed3SPierre Pronchery { 1518*b077aed3SPierre Pronchery char buf[1][BSIZE]; 1519*b077aed3SPierre Pronchery BIO *out = NULL; 1520*b077aed3SPierre Pronchery int ret = 0; 1521*b077aed3SPierre Pronchery ASN1_INTEGER *ai = NULL; 1522*b077aed3SPierre Pronchery int j; 1523*b077aed3SPierre Pronchery 1524*b077aed3SPierre Pronchery if (suffix == NULL) 1525*b077aed3SPierre Pronchery j = strlen(serialfile); 1526*b077aed3SPierre Pronchery else 1527*b077aed3SPierre Pronchery j = strlen(serialfile) + strlen(suffix) + 1; 1528*b077aed3SPierre Pronchery if (j >= BSIZE) { 1529*b077aed3SPierre Pronchery BIO_printf(bio_err, "File name too long\n"); 1530*b077aed3SPierre Pronchery goto err; 1531*b077aed3SPierre Pronchery } 1532*b077aed3SPierre Pronchery 1533*b077aed3SPierre Pronchery if (suffix == NULL) 1534*b077aed3SPierre Pronchery OPENSSL_strlcpy(buf[0], serialfile, BSIZE); 1535*b077aed3SPierre Pronchery else { 1536*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_VMS 1537*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); 1538*b077aed3SPierre Pronchery #else 1539*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); 1540*b077aed3SPierre Pronchery #endif 1541*b077aed3SPierre Pronchery } 1542*b077aed3SPierre Pronchery out = BIO_new_file(buf[0], "w"); 1543*b077aed3SPierre Pronchery if (out == NULL) { 1544*b077aed3SPierre Pronchery goto err; 1545*b077aed3SPierre Pronchery } 1546*b077aed3SPierre Pronchery 1547*b077aed3SPierre Pronchery if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { 1548*b077aed3SPierre Pronchery BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); 1549*b077aed3SPierre Pronchery goto err; 1550*b077aed3SPierre Pronchery } 1551*b077aed3SPierre Pronchery i2a_ASN1_INTEGER(out, ai); 1552*b077aed3SPierre Pronchery BIO_puts(out, "\n"); 1553*b077aed3SPierre Pronchery ret = 1; 1554*b077aed3SPierre Pronchery if (retai) { 1555*b077aed3SPierre Pronchery *retai = ai; 1556*b077aed3SPierre Pronchery ai = NULL; 1557*b077aed3SPierre Pronchery } 1558*b077aed3SPierre Pronchery err: 1559*b077aed3SPierre Pronchery if (!ret) 1560*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1561*b077aed3SPierre Pronchery BIO_free_all(out); 1562*b077aed3SPierre Pronchery ASN1_INTEGER_free(ai); 1563*b077aed3SPierre Pronchery return ret; 1564*b077aed3SPierre Pronchery } 1565*b077aed3SPierre Pronchery 1566*b077aed3SPierre Pronchery int rotate_serial(const char *serialfile, const char *new_suffix, 1567*b077aed3SPierre Pronchery const char *old_suffix) 1568*b077aed3SPierre Pronchery { 1569*b077aed3SPierre Pronchery char buf[2][BSIZE]; 1570*b077aed3SPierre Pronchery int i, j; 1571*b077aed3SPierre Pronchery 1572*b077aed3SPierre Pronchery i = strlen(serialfile) + strlen(old_suffix); 1573*b077aed3SPierre Pronchery j = strlen(serialfile) + strlen(new_suffix); 1574*b077aed3SPierre Pronchery if (i > j) 1575*b077aed3SPierre Pronchery j = i; 1576*b077aed3SPierre Pronchery if (j + 1 >= BSIZE) { 1577*b077aed3SPierre Pronchery BIO_printf(bio_err, "File name too long\n"); 1578*b077aed3SPierre Pronchery goto err; 1579*b077aed3SPierre Pronchery } 1580*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_VMS 1581*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); 1582*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); 1583*b077aed3SPierre Pronchery #else 1584*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); 1585*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); 1586*b077aed3SPierre Pronchery #endif 1587*b077aed3SPierre Pronchery if (rename(serialfile, buf[1]) < 0 && errno != ENOENT 1588*b077aed3SPierre Pronchery #ifdef ENOTDIR 1589*b077aed3SPierre Pronchery && errno != ENOTDIR 1590*b077aed3SPierre Pronchery #endif 1591*b077aed3SPierre Pronchery ) { 1592*b077aed3SPierre Pronchery BIO_printf(bio_err, 1593*b077aed3SPierre Pronchery "Unable to rename %s to %s\n", serialfile, buf[1]); 1594*b077aed3SPierre Pronchery perror("reason"); 1595*b077aed3SPierre Pronchery goto err; 1596*b077aed3SPierre Pronchery } 1597*b077aed3SPierre Pronchery if (rename(buf[0], serialfile) < 0) { 1598*b077aed3SPierre Pronchery BIO_printf(bio_err, 1599*b077aed3SPierre Pronchery "Unable to rename %s to %s\n", buf[0], serialfile); 1600*b077aed3SPierre Pronchery perror("reason"); 1601*b077aed3SPierre Pronchery rename(buf[1], serialfile); 1602*b077aed3SPierre Pronchery goto err; 1603*b077aed3SPierre Pronchery } 1604*b077aed3SPierre Pronchery return 1; 1605*b077aed3SPierre Pronchery err: 1606*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1607*b077aed3SPierre Pronchery return 0; 1608*b077aed3SPierre Pronchery } 1609*b077aed3SPierre Pronchery 1610*b077aed3SPierre Pronchery int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 1611*b077aed3SPierre Pronchery { 1612*b077aed3SPierre Pronchery BIGNUM *btmp; 1613*b077aed3SPierre Pronchery int ret = 0; 1614*b077aed3SPierre Pronchery 1615*b077aed3SPierre Pronchery btmp = b == NULL ? BN_new() : b; 1616*b077aed3SPierre Pronchery if (btmp == NULL) 1617*b077aed3SPierre Pronchery return 0; 1618*b077aed3SPierre Pronchery 1619*b077aed3SPierre Pronchery if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) 1620*b077aed3SPierre Pronchery goto error; 1621*b077aed3SPierre Pronchery if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 1622*b077aed3SPierre Pronchery goto error; 1623*b077aed3SPierre Pronchery 1624*b077aed3SPierre Pronchery ret = 1; 1625*b077aed3SPierre Pronchery 1626*b077aed3SPierre Pronchery error: 1627*b077aed3SPierre Pronchery 1628*b077aed3SPierre Pronchery if (btmp != b) 1629*b077aed3SPierre Pronchery BN_free(btmp); 1630*b077aed3SPierre Pronchery 1631*b077aed3SPierre Pronchery return ret; 1632*b077aed3SPierre Pronchery } 1633*b077aed3SPierre Pronchery 1634*b077aed3SPierre Pronchery CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) 1635*b077aed3SPierre Pronchery { 1636*b077aed3SPierre Pronchery CA_DB *retdb = NULL; 1637*b077aed3SPierre Pronchery TXT_DB *tmpdb = NULL; 1638*b077aed3SPierre Pronchery BIO *in; 1639*b077aed3SPierre Pronchery CONF *dbattr_conf = NULL; 1640*b077aed3SPierre Pronchery char buf[BSIZE]; 1641*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 1642*b077aed3SPierre Pronchery FILE *dbfp; 1643*b077aed3SPierre Pronchery struct stat dbst; 1644*b077aed3SPierre Pronchery #endif 1645*b077aed3SPierre Pronchery 1646*b077aed3SPierre Pronchery in = BIO_new_file(dbfile, "r"); 1647*b077aed3SPierre Pronchery if (in == NULL) 1648*b077aed3SPierre Pronchery goto err; 1649*b077aed3SPierre Pronchery 1650*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 1651*b077aed3SPierre Pronchery BIO_get_fp(in, &dbfp); 1652*b077aed3SPierre Pronchery if (fstat(fileno(dbfp), &dbst) == -1) { 1653*b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_SYS, errno, 1654*b077aed3SPierre Pronchery "calling fstat(%s)", dbfile); 1655*b077aed3SPierre Pronchery goto err; 1656*b077aed3SPierre Pronchery } 1657*b077aed3SPierre Pronchery #endif 1658*b077aed3SPierre Pronchery 1659*b077aed3SPierre Pronchery if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) 1660*b077aed3SPierre Pronchery goto err; 1661*b077aed3SPierre Pronchery 1662*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_VMS 1663*b077aed3SPierre Pronchery BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); 1664*b077aed3SPierre Pronchery #else 1665*b077aed3SPierre Pronchery BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); 1666*b077aed3SPierre Pronchery #endif 1667*b077aed3SPierre Pronchery dbattr_conf = app_load_config_quiet(buf); 1668*b077aed3SPierre Pronchery 1669*b077aed3SPierre Pronchery retdb = app_malloc(sizeof(*retdb), "new DB"); 1670*b077aed3SPierre Pronchery retdb->db = tmpdb; 1671*b077aed3SPierre Pronchery tmpdb = NULL; 1672*b077aed3SPierre Pronchery if (db_attr) 1673*b077aed3SPierre Pronchery retdb->attributes = *db_attr; 1674*b077aed3SPierre Pronchery else { 1675*b077aed3SPierre Pronchery retdb->attributes.unique_subject = 1; 1676*b077aed3SPierre Pronchery } 1677*b077aed3SPierre Pronchery 1678*b077aed3SPierre Pronchery if (dbattr_conf) { 1679*b077aed3SPierre Pronchery char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); 1680*b077aed3SPierre Pronchery if (p) { 1681*b077aed3SPierre Pronchery retdb->attributes.unique_subject = parse_yesno(p, 1); 1682*b077aed3SPierre Pronchery } 1683*b077aed3SPierre Pronchery } 1684*b077aed3SPierre Pronchery 1685*b077aed3SPierre Pronchery retdb->dbfname = OPENSSL_strdup(dbfile); 1686*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 1687*b077aed3SPierre Pronchery retdb->dbst = dbst; 1688*b077aed3SPierre Pronchery #endif 1689*b077aed3SPierre Pronchery 1690*b077aed3SPierre Pronchery err: 1691*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1692*b077aed3SPierre Pronchery NCONF_free(dbattr_conf); 1693*b077aed3SPierre Pronchery TXT_DB_free(tmpdb); 1694*b077aed3SPierre Pronchery BIO_free_all(in); 1695*b077aed3SPierre Pronchery return retdb; 1696*b077aed3SPierre Pronchery } 1697*b077aed3SPierre Pronchery 1698*b077aed3SPierre Pronchery /* 1699*b077aed3SPierre Pronchery * Returns > 0 on success, <= 0 on error 1700*b077aed3SPierre Pronchery */ 1701*b077aed3SPierre Pronchery int index_index(CA_DB *db) 1702*b077aed3SPierre Pronchery { 1703*b077aed3SPierre Pronchery if (!TXT_DB_create_index(db->db, DB_serial, NULL, 1704*b077aed3SPierre Pronchery LHASH_HASH_FN(index_serial), 1705*b077aed3SPierre Pronchery LHASH_COMP_FN(index_serial))) { 1706*b077aed3SPierre Pronchery BIO_printf(bio_err, 1707*b077aed3SPierre Pronchery "Error creating serial number index:(%ld,%ld,%ld)\n", 1708*b077aed3SPierre Pronchery db->db->error, db->db->arg1, db->db->arg2); 1709*b077aed3SPierre Pronchery goto err; 1710*b077aed3SPierre Pronchery } 1711*b077aed3SPierre Pronchery 1712*b077aed3SPierre Pronchery if (db->attributes.unique_subject 1713*b077aed3SPierre Pronchery && !TXT_DB_create_index(db->db, DB_name, index_name_qual, 1714*b077aed3SPierre Pronchery LHASH_HASH_FN(index_name), 1715*b077aed3SPierre Pronchery LHASH_COMP_FN(index_name))) { 1716*b077aed3SPierre Pronchery BIO_printf(bio_err, "Error creating name index:(%ld,%ld,%ld)\n", 1717*b077aed3SPierre Pronchery db->db->error, db->db->arg1, db->db->arg2); 1718*b077aed3SPierre Pronchery goto err; 1719*b077aed3SPierre Pronchery } 1720*b077aed3SPierre Pronchery return 1; 1721*b077aed3SPierre Pronchery err: 1722*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1723*b077aed3SPierre Pronchery return 0; 1724*b077aed3SPierre Pronchery } 1725*b077aed3SPierre Pronchery 1726*b077aed3SPierre Pronchery int save_index(const char *dbfile, const char *suffix, CA_DB *db) 1727*b077aed3SPierre Pronchery { 1728*b077aed3SPierre Pronchery char buf[3][BSIZE]; 1729*b077aed3SPierre Pronchery BIO *out; 1730*b077aed3SPierre Pronchery int j; 1731*b077aed3SPierre Pronchery 1732*b077aed3SPierre Pronchery j = strlen(dbfile) + strlen(suffix); 1733*b077aed3SPierre Pronchery if (j + 6 >= BSIZE) { 1734*b077aed3SPierre Pronchery BIO_printf(bio_err, "File name too long\n"); 1735*b077aed3SPierre Pronchery goto err; 1736*b077aed3SPierre Pronchery } 1737*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_VMS 1738*b077aed3SPierre Pronchery j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); 1739*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); 1740*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); 1741*b077aed3SPierre Pronchery #else 1742*b077aed3SPierre Pronchery j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); 1743*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); 1744*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); 1745*b077aed3SPierre Pronchery #endif 1746*b077aed3SPierre Pronchery out = BIO_new_file(buf[0], "w"); 1747*b077aed3SPierre Pronchery if (out == NULL) { 1748*b077aed3SPierre Pronchery perror(dbfile); 1749*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to open '%s'\n", dbfile); 1750*b077aed3SPierre Pronchery goto err; 1751*b077aed3SPierre Pronchery } 1752*b077aed3SPierre Pronchery j = TXT_DB_write(out, db->db); 1753*b077aed3SPierre Pronchery BIO_free(out); 1754*b077aed3SPierre Pronchery if (j <= 0) 1755*b077aed3SPierre Pronchery goto err; 1756*b077aed3SPierre Pronchery 1757*b077aed3SPierre Pronchery out = BIO_new_file(buf[1], "w"); 1758*b077aed3SPierre Pronchery if (out == NULL) { 1759*b077aed3SPierre Pronchery perror(buf[2]); 1760*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to open '%s'\n", buf[2]); 1761*b077aed3SPierre Pronchery goto err; 1762*b077aed3SPierre Pronchery } 1763*b077aed3SPierre Pronchery BIO_printf(out, "unique_subject = %s\n", 1764*b077aed3SPierre Pronchery db->attributes.unique_subject ? "yes" : "no"); 1765*b077aed3SPierre Pronchery BIO_free(out); 1766*b077aed3SPierre Pronchery 1767*b077aed3SPierre Pronchery return 1; 1768*b077aed3SPierre Pronchery err: 1769*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1770*b077aed3SPierre Pronchery return 0; 1771*b077aed3SPierre Pronchery } 1772*b077aed3SPierre Pronchery 1773*b077aed3SPierre Pronchery int rotate_index(const char *dbfile, const char *new_suffix, 1774*b077aed3SPierre Pronchery const char *old_suffix) 1775*b077aed3SPierre Pronchery { 1776*b077aed3SPierre Pronchery char buf[5][BSIZE]; 1777*b077aed3SPierre Pronchery int i, j; 1778*b077aed3SPierre Pronchery 1779*b077aed3SPierre Pronchery i = strlen(dbfile) + strlen(old_suffix); 1780*b077aed3SPierre Pronchery j = strlen(dbfile) + strlen(new_suffix); 1781*b077aed3SPierre Pronchery if (i > j) 1782*b077aed3SPierre Pronchery j = i; 1783*b077aed3SPierre Pronchery if (j + 6 >= BSIZE) { 1784*b077aed3SPierre Pronchery BIO_printf(bio_err, "File name too long\n"); 1785*b077aed3SPierre Pronchery goto err; 1786*b077aed3SPierre Pronchery } 1787*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_VMS 1788*b077aed3SPierre Pronchery j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); 1789*b077aed3SPierre Pronchery j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); 1790*b077aed3SPierre Pronchery j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); 1791*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); 1792*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); 1793*b077aed3SPierre Pronchery #else 1794*b077aed3SPierre Pronchery j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); 1795*b077aed3SPierre Pronchery j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); 1796*b077aed3SPierre Pronchery j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); 1797*b077aed3SPierre Pronchery j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); 1798*b077aed3SPierre Pronchery j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); 1799*b077aed3SPierre Pronchery #endif 1800*b077aed3SPierre Pronchery if (rename(dbfile, buf[1]) < 0 && errno != ENOENT 1801*b077aed3SPierre Pronchery #ifdef ENOTDIR 1802*b077aed3SPierre Pronchery && errno != ENOTDIR 1803*b077aed3SPierre Pronchery #endif 1804*b077aed3SPierre Pronchery ) { 1805*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to rename %s to %s\n", dbfile, buf[1]); 1806*b077aed3SPierre Pronchery perror("reason"); 1807*b077aed3SPierre Pronchery goto err; 1808*b077aed3SPierre Pronchery } 1809*b077aed3SPierre Pronchery if (rename(buf[0], dbfile) < 0) { 1810*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[0], dbfile); 1811*b077aed3SPierre Pronchery perror("reason"); 1812*b077aed3SPierre Pronchery rename(buf[1], dbfile); 1813*b077aed3SPierre Pronchery goto err; 1814*b077aed3SPierre Pronchery } 1815*b077aed3SPierre Pronchery if (rename(buf[4], buf[3]) < 0 && errno != ENOENT 1816*b077aed3SPierre Pronchery #ifdef ENOTDIR 1817*b077aed3SPierre Pronchery && errno != ENOTDIR 1818*b077aed3SPierre Pronchery #endif 1819*b077aed3SPierre Pronchery ) { 1820*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[4], buf[3]); 1821*b077aed3SPierre Pronchery perror("reason"); 1822*b077aed3SPierre Pronchery rename(dbfile, buf[0]); 1823*b077aed3SPierre Pronchery rename(buf[1], dbfile); 1824*b077aed3SPierre Pronchery goto err; 1825*b077aed3SPierre Pronchery } 1826*b077aed3SPierre Pronchery if (rename(buf[2], buf[4]) < 0) { 1827*b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to rename %s to %s\n", buf[2], buf[4]); 1828*b077aed3SPierre Pronchery perror("reason"); 1829*b077aed3SPierre Pronchery rename(buf[3], buf[4]); 1830*b077aed3SPierre Pronchery rename(dbfile, buf[0]); 1831*b077aed3SPierre Pronchery rename(buf[1], dbfile); 1832*b077aed3SPierre Pronchery goto err; 1833*b077aed3SPierre Pronchery } 1834*b077aed3SPierre Pronchery return 1; 1835*b077aed3SPierre Pronchery err: 1836*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1837*b077aed3SPierre Pronchery return 0; 1838*b077aed3SPierre Pronchery } 1839*b077aed3SPierre Pronchery 1840*b077aed3SPierre Pronchery void free_index(CA_DB *db) 1841*b077aed3SPierre Pronchery { 1842*b077aed3SPierre Pronchery if (db) { 1843*b077aed3SPierre Pronchery TXT_DB_free(db->db); 1844*b077aed3SPierre Pronchery OPENSSL_free(db->dbfname); 1845*b077aed3SPierre Pronchery OPENSSL_free(db); 1846*b077aed3SPierre Pronchery } 1847*b077aed3SPierre Pronchery } 1848*b077aed3SPierre Pronchery 1849*b077aed3SPierre Pronchery int parse_yesno(const char *str, int def) 1850*b077aed3SPierre Pronchery { 1851*b077aed3SPierre Pronchery if (str) { 1852*b077aed3SPierre Pronchery switch (*str) { 1853*b077aed3SPierre Pronchery case 'f': /* false */ 1854*b077aed3SPierre Pronchery case 'F': /* FALSE */ 1855*b077aed3SPierre Pronchery case 'n': /* no */ 1856*b077aed3SPierre Pronchery case 'N': /* NO */ 1857*b077aed3SPierre Pronchery case '0': /* 0 */ 1858*b077aed3SPierre Pronchery return 0; 1859*b077aed3SPierre Pronchery case 't': /* true */ 1860*b077aed3SPierre Pronchery case 'T': /* TRUE */ 1861*b077aed3SPierre Pronchery case 'y': /* yes */ 1862*b077aed3SPierre Pronchery case 'Y': /* YES */ 1863*b077aed3SPierre Pronchery case '1': /* 1 */ 1864*b077aed3SPierre Pronchery return 1; 1865*b077aed3SPierre Pronchery } 1866*b077aed3SPierre Pronchery } 1867*b077aed3SPierre Pronchery return def; 1868*b077aed3SPierre Pronchery } 1869*b077aed3SPierre Pronchery 1870*b077aed3SPierre Pronchery /* 1871*b077aed3SPierre Pronchery * name is expected to be in the format /type0=value0/type1=value1/type2=... 1872*b077aed3SPierre Pronchery * where + can be used instead of / to form multi-valued RDNs if canmulti 1873*b077aed3SPierre Pronchery * and characters may be escaped by \ 1874*b077aed3SPierre Pronchery */ 1875*b077aed3SPierre Pronchery X509_NAME *parse_name(const char *cp, int chtype, int canmulti, 1876*b077aed3SPierre Pronchery const char *desc) 1877*b077aed3SPierre Pronchery { 1878*b077aed3SPierre Pronchery int nextismulti = 0; 1879*b077aed3SPierre Pronchery char *work; 1880*b077aed3SPierre Pronchery X509_NAME *n; 1881*b077aed3SPierre Pronchery 1882*b077aed3SPierre Pronchery if (*cp++ != '/') { 1883*b077aed3SPierre Pronchery BIO_printf(bio_err, 1884*b077aed3SPierre Pronchery "%s: %s name is expected to be in the format " 1885*b077aed3SPierre Pronchery "/type0=value0/type1=value1/type2=... where characters may " 1886*b077aed3SPierre Pronchery "be escaped by \\. This name is not in that format: '%s'\n", 1887*b077aed3SPierre Pronchery opt_getprog(), desc, --cp); 1888*b077aed3SPierre Pronchery return NULL; 1889*b077aed3SPierre Pronchery } 1890*b077aed3SPierre Pronchery 1891*b077aed3SPierre Pronchery n = X509_NAME_new(); 1892*b077aed3SPierre Pronchery if (n == NULL) { 1893*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog()); 1894*b077aed3SPierre Pronchery return NULL; 1895*b077aed3SPierre Pronchery } 1896*b077aed3SPierre Pronchery work = OPENSSL_strdup(cp); 1897*b077aed3SPierre Pronchery if (work == NULL) { 1898*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s: Error copying %s name input\n", 1899*b077aed3SPierre Pronchery opt_getprog(), desc); 1900*b077aed3SPierre Pronchery goto err; 1901*b077aed3SPierre Pronchery } 1902*b077aed3SPierre Pronchery 1903*b077aed3SPierre Pronchery while (*cp != '\0') { 1904*b077aed3SPierre Pronchery char *bp = work; 1905*b077aed3SPierre Pronchery char *typestr = bp; 1906*b077aed3SPierre Pronchery unsigned char *valstr; 1907*b077aed3SPierre Pronchery int nid; 1908*b077aed3SPierre Pronchery int ismulti = nextismulti; 1909*b077aed3SPierre Pronchery nextismulti = 0; 1910*b077aed3SPierre Pronchery 1911*b077aed3SPierre Pronchery /* Collect the type */ 1912*b077aed3SPierre Pronchery while (*cp != '\0' && *cp != '=') 1913*b077aed3SPierre Pronchery *bp++ = *cp++; 1914*b077aed3SPierre Pronchery *bp++ = '\0'; 1915*b077aed3SPierre Pronchery if (*cp == '\0') { 1916*b077aed3SPierre Pronchery BIO_printf(bio_err, 1917*b077aed3SPierre Pronchery "%s: Missing '=' after RDN type string '%s' in %s name string\n", 1918*b077aed3SPierre Pronchery opt_getprog(), typestr, desc); 1919*b077aed3SPierre Pronchery goto err; 1920*b077aed3SPierre Pronchery } 1921*b077aed3SPierre Pronchery ++cp; 1922*b077aed3SPierre Pronchery 1923*b077aed3SPierre Pronchery /* Collect the value. */ 1924*b077aed3SPierre Pronchery valstr = (unsigned char *)bp; 1925*b077aed3SPierre Pronchery for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) { 1926*b077aed3SPierre Pronchery /* unescaped '+' symbol string signals further member of multiRDN */ 1927*b077aed3SPierre Pronchery if (canmulti && *cp == '+') { 1928*b077aed3SPierre Pronchery nextismulti = 1; 1929*b077aed3SPierre Pronchery break; 1930*b077aed3SPierre Pronchery } 1931*b077aed3SPierre Pronchery if (*cp == '\\' && *++cp == '\0') { 1932*b077aed3SPierre Pronchery BIO_printf(bio_err, 1933*b077aed3SPierre Pronchery "%s: Escape character at end of %s name string\n", 1934*b077aed3SPierre Pronchery opt_getprog(), desc); 1935*b077aed3SPierre Pronchery goto err; 1936*b077aed3SPierre Pronchery } 1937*b077aed3SPierre Pronchery } 1938*b077aed3SPierre Pronchery *bp++ = '\0'; 1939*b077aed3SPierre Pronchery 1940*b077aed3SPierre Pronchery /* If not at EOS (must be + or /), move forward. */ 1941*b077aed3SPierre Pronchery if (*cp != '\0') 1942*b077aed3SPierre Pronchery ++cp; 1943*b077aed3SPierre Pronchery 1944*b077aed3SPierre Pronchery /* Parse */ 1945*b077aed3SPierre Pronchery nid = OBJ_txt2nid(typestr); 1946*b077aed3SPierre Pronchery if (nid == NID_undef) { 1947*b077aed3SPierre Pronchery BIO_printf(bio_err, 1948*b077aed3SPierre Pronchery "%s: Skipping unknown %s name attribute \"%s\"\n", 1949*b077aed3SPierre Pronchery opt_getprog(), desc, typestr); 1950*b077aed3SPierre Pronchery if (ismulti) 1951*b077aed3SPierre Pronchery BIO_printf(bio_err, 1952*b077aed3SPierre Pronchery "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n"); 1953*b077aed3SPierre Pronchery continue; 1954*b077aed3SPierre Pronchery } 1955*b077aed3SPierre Pronchery if (*valstr == '\0') { 1956*b077aed3SPierre Pronchery BIO_printf(bio_err, 1957*b077aed3SPierre Pronchery "%s: No value provided for %s name attribute \"%s\", skipped\n", 1958*b077aed3SPierre Pronchery opt_getprog(), desc, typestr); 1959*b077aed3SPierre Pronchery continue; 1960*b077aed3SPierre Pronchery } 1961*b077aed3SPierre Pronchery if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 1962*b077aed3SPierre Pronchery valstr, strlen((char *)valstr), 1963*b077aed3SPierre Pronchery -1, ismulti ? -1 : 0)) { 1964*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 1965*b077aed3SPierre Pronchery BIO_printf(bio_err, 1966*b077aed3SPierre Pronchery "%s: Error adding %s name attribute \"/%s=%s\"\n", 1967*b077aed3SPierre Pronchery opt_getprog(), desc, typestr ,valstr); 1968*b077aed3SPierre Pronchery goto err; 1969*b077aed3SPierre Pronchery } 1970*b077aed3SPierre Pronchery } 1971*b077aed3SPierre Pronchery 1972*b077aed3SPierre Pronchery OPENSSL_free(work); 1973*b077aed3SPierre Pronchery return n; 1974*b077aed3SPierre Pronchery 1975*b077aed3SPierre Pronchery err: 1976*b077aed3SPierre Pronchery X509_NAME_free(n); 1977*b077aed3SPierre Pronchery OPENSSL_free(work); 1978*b077aed3SPierre Pronchery return NULL; 1979*b077aed3SPierre Pronchery } 1980*b077aed3SPierre Pronchery 1981*b077aed3SPierre Pronchery /* 1982*b077aed3SPierre Pronchery * Read whole contents of a BIO into an allocated memory buffer and return 1983*b077aed3SPierre Pronchery * it. 1984*b077aed3SPierre Pronchery */ 1985*b077aed3SPierre Pronchery 1986*b077aed3SPierre Pronchery int bio_to_mem(unsigned char **out, int maxlen, BIO *in) 1987*b077aed3SPierre Pronchery { 1988*b077aed3SPierre Pronchery BIO *mem; 1989*b077aed3SPierre Pronchery int len, ret; 1990*b077aed3SPierre Pronchery unsigned char tbuf[1024]; 1991*b077aed3SPierre Pronchery 1992*b077aed3SPierre Pronchery mem = BIO_new(BIO_s_mem()); 1993*b077aed3SPierre Pronchery if (mem == NULL) 1994*b077aed3SPierre Pronchery return -1; 1995*b077aed3SPierre Pronchery for (;;) { 1996*b077aed3SPierre Pronchery if ((maxlen != -1) && maxlen < 1024) 1997*b077aed3SPierre Pronchery len = maxlen; 1998*b077aed3SPierre Pronchery else 1999*b077aed3SPierre Pronchery len = 1024; 2000*b077aed3SPierre Pronchery len = BIO_read(in, tbuf, len); 2001*b077aed3SPierre Pronchery if (len < 0) { 2002*b077aed3SPierre Pronchery BIO_free(mem); 2003*b077aed3SPierre Pronchery return -1; 2004*b077aed3SPierre Pronchery } 2005*b077aed3SPierre Pronchery if (len == 0) 2006*b077aed3SPierre Pronchery break; 2007*b077aed3SPierre Pronchery if (BIO_write(mem, tbuf, len) != len) { 2008*b077aed3SPierre Pronchery BIO_free(mem); 2009*b077aed3SPierre Pronchery return -1; 2010*b077aed3SPierre Pronchery } 2011*b077aed3SPierre Pronchery maxlen -= len; 2012*b077aed3SPierre Pronchery 2013*b077aed3SPierre Pronchery if (maxlen == 0) 2014*b077aed3SPierre Pronchery break; 2015*b077aed3SPierre Pronchery } 2016*b077aed3SPierre Pronchery ret = BIO_get_mem_data(mem, (char **)out); 2017*b077aed3SPierre Pronchery BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); 2018*b077aed3SPierre Pronchery BIO_free(mem); 2019*b077aed3SPierre Pronchery return ret; 2020*b077aed3SPierre Pronchery } 2021*b077aed3SPierre Pronchery 2022*b077aed3SPierre Pronchery int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) 2023*b077aed3SPierre Pronchery { 2024*b077aed3SPierre Pronchery int rv = 0; 2025*b077aed3SPierre Pronchery char *stmp, *vtmp = NULL; 2026*b077aed3SPierre Pronchery 2027*b077aed3SPierre Pronchery stmp = OPENSSL_strdup(value); 2028*b077aed3SPierre Pronchery if (stmp == NULL) 2029*b077aed3SPierre Pronchery return -1; 2030*b077aed3SPierre Pronchery vtmp = strchr(stmp, ':'); 2031*b077aed3SPierre Pronchery if (vtmp == NULL) 2032*b077aed3SPierre Pronchery goto err; 2033*b077aed3SPierre Pronchery 2034*b077aed3SPierre Pronchery *vtmp = 0; 2035*b077aed3SPierre Pronchery vtmp++; 2036*b077aed3SPierre Pronchery rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); 2037*b077aed3SPierre Pronchery 2038*b077aed3SPierre Pronchery err: 2039*b077aed3SPierre Pronchery OPENSSL_free(stmp); 2040*b077aed3SPierre Pronchery return rv; 2041*b077aed3SPierre Pronchery } 2042*b077aed3SPierre Pronchery 2043*b077aed3SPierre Pronchery static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) 2044*b077aed3SPierre Pronchery { 2045*b077aed3SPierre Pronchery X509_POLICY_NODE *node; 2046*b077aed3SPierre Pronchery int i; 2047*b077aed3SPierre Pronchery 2048*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s Policies:", name); 2049*b077aed3SPierre Pronchery if (nodes) { 2050*b077aed3SPierre Pronchery BIO_puts(bio_err, "\n"); 2051*b077aed3SPierre Pronchery for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { 2052*b077aed3SPierre Pronchery node = sk_X509_POLICY_NODE_value(nodes, i); 2053*b077aed3SPierre Pronchery X509_POLICY_NODE_print(bio_err, node, 2); 2054*b077aed3SPierre Pronchery } 2055*b077aed3SPierre Pronchery } else { 2056*b077aed3SPierre Pronchery BIO_puts(bio_err, " <empty>\n"); 2057*b077aed3SPierre Pronchery } 2058*b077aed3SPierre Pronchery } 2059*b077aed3SPierre Pronchery 2060*b077aed3SPierre Pronchery void policies_print(X509_STORE_CTX *ctx) 2061*b077aed3SPierre Pronchery { 2062*b077aed3SPierre Pronchery X509_POLICY_TREE *tree; 2063*b077aed3SPierre Pronchery int explicit_policy; 2064*b077aed3SPierre Pronchery tree = X509_STORE_CTX_get0_policy_tree(ctx); 2065*b077aed3SPierre Pronchery explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); 2066*b077aed3SPierre Pronchery 2067*b077aed3SPierre Pronchery BIO_printf(bio_err, "Require explicit Policy: %s\n", 2068*b077aed3SPierre Pronchery explicit_policy ? "True" : "False"); 2069*b077aed3SPierre Pronchery 2070*b077aed3SPierre Pronchery nodes_print("Authority", X509_policy_tree_get0_policies(tree)); 2071*b077aed3SPierre Pronchery nodes_print("User", X509_policy_tree_get0_user_policies(tree)); 2072*b077aed3SPierre Pronchery } 2073*b077aed3SPierre Pronchery 2074*b077aed3SPierre Pronchery /*- 2075*b077aed3SPierre Pronchery * next_protos_parse parses a comma separated list of strings into a string 2076*b077aed3SPierre Pronchery * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. 2077*b077aed3SPierre Pronchery * outlen: (output) set to the length of the resulting buffer on success. 2078*b077aed3SPierre Pronchery * err: (maybe NULL) on failure, an error message line is written to this BIO. 2079*b077aed3SPierre Pronchery * in: a NUL terminated string like "abc,def,ghi" 2080*b077aed3SPierre Pronchery * 2081*b077aed3SPierre Pronchery * returns: a malloc'd buffer or NULL on failure. 2082*b077aed3SPierre Pronchery */ 2083*b077aed3SPierre Pronchery unsigned char *next_protos_parse(size_t *outlen, const char *in) 2084*b077aed3SPierre Pronchery { 2085*b077aed3SPierre Pronchery size_t len; 2086*b077aed3SPierre Pronchery unsigned char *out; 2087*b077aed3SPierre Pronchery size_t i, start = 0; 2088*b077aed3SPierre Pronchery size_t skipped = 0; 2089*b077aed3SPierre Pronchery 2090*b077aed3SPierre Pronchery len = strlen(in); 2091*b077aed3SPierre Pronchery if (len == 0 || len >= 65535) 2092*b077aed3SPierre Pronchery return NULL; 2093*b077aed3SPierre Pronchery 2094*b077aed3SPierre Pronchery out = app_malloc(len + 1, "NPN buffer"); 2095*b077aed3SPierre Pronchery for (i = 0; i <= len; ++i) { 2096*b077aed3SPierre Pronchery if (i == len || in[i] == ',') { 2097*b077aed3SPierre Pronchery /* 2098*b077aed3SPierre Pronchery * Zero-length ALPN elements are invalid on the wire, we could be 2099*b077aed3SPierre Pronchery * strict and reject the entire string, but just ignoring extra 2100*b077aed3SPierre Pronchery * commas seems harmless and more friendly. 2101*b077aed3SPierre Pronchery * 2102*b077aed3SPierre Pronchery * Every comma we skip in this way puts the input buffer another 2103*b077aed3SPierre Pronchery * byte ahead of the output buffer, so all stores into the output 2104*b077aed3SPierre Pronchery * buffer need to be decremented by the number commas skipped. 2105*b077aed3SPierre Pronchery */ 2106*b077aed3SPierre Pronchery if (i == start) { 2107*b077aed3SPierre Pronchery ++start; 2108*b077aed3SPierre Pronchery ++skipped; 2109*b077aed3SPierre Pronchery continue; 2110*b077aed3SPierre Pronchery } 2111*b077aed3SPierre Pronchery if (i - start > 255) { 2112*b077aed3SPierre Pronchery OPENSSL_free(out); 2113*b077aed3SPierre Pronchery return NULL; 2114*b077aed3SPierre Pronchery } 2115*b077aed3SPierre Pronchery out[start-skipped] = (unsigned char)(i - start); 2116*b077aed3SPierre Pronchery start = i + 1; 2117*b077aed3SPierre Pronchery } else { 2118*b077aed3SPierre Pronchery out[i + 1 - skipped] = in[i]; 2119*b077aed3SPierre Pronchery } 2120*b077aed3SPierre Pronchery } 2121*b077aed3SPierre Pronchery 2122*b077aed3SPierre Pronchery if (len <= skipped) { 2123*b077aed3SPierre Pronchery OPENSSL_free(out); 2124*b077aed3SPierre Pronchery return NULL; 2125*b077aed3SPierre Pronchery } 2126*b077aed3SPierre Pronchery 2127*b077aed3SPierre Pronchery *outlen = len + 1 - skipped; 2128*b077aed3SPierre Pronchery return out; 2129*b077aed3SPierre Pronchery } 2130*b077aed3SPierre Pronchery 2131*b077aed3SPierre Pronchery void print_cert_checks(BIO *bio, X509 *x, 2132*b077aed3SPierre Pronchery const char *checkhost, 2133*b077aed3SPierre Pronchery const char *checkemail, const char *checkip) 2134*b077aed3SPierre Pronchery { 2135*b077aed3SPierre Pronchery if (x == NULL) 2136*b077aed3SPierre Pronchery return; 2137*b077aed3SPierre Pronchery if (checkhost) { 2138*b077aed3SPierre Pronchery BIO_printf(bio, "Hostname %s does%s match certificate\n", 2139*b077aed3SPierre Pronchery checkhost, 2140*b077aed3SPierre Pronchery X509_check_host(x, checkhost, 0, 0, NULL) == 1 2141*b077aed3SPierre Pronchery ? "" : " NOT"); 2142*b077aed3SPierre Pronchery } 2143*b077aed3SPierre Pronchery 2144*b077aed3SPierre Pronchery if (checkemail) { 2145*b077aed3SPierre Pronchery BIO_printf(bio, "Email %s does%s match certificate\n", 2146*b077aed3SPierre Pronchery checkemail, X509_check_email(x, checkemail, 0, 0) 2147*b077aed3SPierre Pronchery ? "" : " NOT"); 2148*b077aed3SPierre Pronchery } 2149*b077aed3SPierre Pronchery 2150*b077aed3SPierre Pronchery if (checkip) { 2151*b077aed3SPierre Pronchery BIO_printf(bio, "IP %s does%s match certificate\n", 2152*b077aed3SPierre Pronchery checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); 2153*b077aed3SPierre Pronchery } 2154*b077aed3SPierre Pronchery } 2155*b077aed3SPierre Pronchery 2156*b077aed3SPierre Pronchery static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts) 2157*b077aed3SPierre Pronchery { 2158*b077aed3SPierre Pronchery int i; 2159*b077aed3SPierre Pronchery 2160*b077aed3SPierre Pronchery if (opts == NULL) 2161*b077aed3SPierre Pronchery return 1; 2162*b077aed3SPierre Pronchery 2163*b077aed3SPierre Pronchery for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { 2164*b077aed3SPierre Pronchery char *opt = sk_OPENSSL_STRING_value(opts, i); 2165*b077aed3SPierre Pronchery if (pkey_ctrl_string(pkctx, opt) <= 0) { 2166*b077aed3SPierre Pronchery BIO_printf(bio_err, "parameter error \"%s\"\n", opt); 2167*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 2168*b077aed3SPierre Pronchery return 0; 2169*b077aed3SPierre Pronchery } 2170*b077aed3SPierre Pronchery } 2171*b077aed3SPierre Pronchery 2172*b077aed3SPierre Pronchery return 1; 2173*b077aed3SPierre Pronchery } 2174*b077aed3SPierre Pronchery 2175*b077aed3SPierre Pronchery static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts) 2176*b077aed3SPierre Pronchery { 2177*b077aed3SPierre Pronchery int i; 2178*b077aed3SPierre Pronchery 2179*b077aed3SPierre Pronchery if (opts == NULL) 2180*b077aed3SPierre Pronchery return 1; 2181*b077aed3SPierre Pronchery 2182*b077aed3SPierre Pronchery for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { 2183*b077aed3SPierre Pronchery char *opt = sk_OPENSSL_STRING_value(opts, i); 2184*b077aed3SPierre Pronchery if (x509_ctrl_string(x, opt) <= 0) { 2185*b077aed3SPierre Pronchery BIO_printf(bio_err, "parameter error \"%s\"\n", opt); 2186*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 2187*b077aed3SPierre Pronchery return 0; 2188*b077aed3SPierre Pronchery } 2189*b077aed3SPierre Pronchery } 2190*b077aed3SPierre Pronchery 2191*b077aed3SPierre Pronchery return 1; 2192*b077aed3SPierre Pronchery } 2193*b077aed3SPierre Pronchery 2194*b077aed3SPierre Pronchery static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts) 2195*b077aed3SPierre Pronchery { 2196*b077aed3SPierre Pronchery int i; 2197*b077aed3SPierre Pronchery 2198*b077aed3SPierre Pronchery if (opts == NULL) 2199*b077aed3SPierre Pronchery return 1; 2200*b077aed3SPierre Pronchery 2201*b077aed3SPierre Pronchery for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { 2202*b077aed3SPierre Pronchery char *opt = sk_OPENSSL_STRING_value(opts, i); 2203*b077aed3SPierre Pronchery if (x509_req_ctrl_string(x, opt) <= 0) { 2204*b077aed3SPierre Pronchery BIO_printf(bio_err, "parameter error \"%s\"\n", opt); 2205*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 2206*b077aed3SPierre Pronchery return 0; 2207*b077aed3SPierre Pronchery } 2208*b077aed3SPierre Pronchery } 2209*b077aed3SPierre Pronchery 2210*b077aed3SPierre Pronchery return 1; 2211*b077aed3SPierre Pronchery } 2212*b077aed3SPierre Pronchery 2213*b077aed3SPierre Pronchery static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, 2214*b077aed3SPierre Pronchery const char *md, STACK_OF(OPENSSL_STRING) *sigopts) 2215*b077aed3SPierre Pronchery { 2216*b077aed3SPierre Pronchery EVP_PKEY_CTX *pkctx = NULL; 2217*b077aed3SPierre Pronchery char def_md[80]; 2218*b077aed3SPierre Pronchery 2219*b077aed3SPierre Pronchery if (ctx == NULL) 2220*b077aed3SPierre Pronchery return 0; 2221*b077aed3SPierre Pronchery /* 2222*b077aed3SPierre Pronchery * EVP_PKEY_get_default_digest_name() returns 2 if the digest is mandatory 2223*b077aed3SPierre Pronchery * for this algorithm. 2224*b077aed3SPierre Pronchery */ 2225*b077aed3SPierre Pronchery if (EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2 2226*b077aed3SPierre Pronchery && strcmp(def_md, "UNDEF") == 0) { 2227*b077aed3SPierre Pronchery /* The signing algorithm requires there to be no digest */ 2228*b077aed3SPierre Pronchery md = NULL; 2229*b077aed3SPierre Pronchery } 2230*b077aed3SPierre Pronchery 2231*b077aed3SPierre Pronchery return EVP_DigestSignInit_ex(ctx, &pkctx, md, app_get0_libctx(), 2232*b077aed3SPierre Pronchery app_get0_propq(), pkey, NULL) 2233*b077aed3SPierre Pronchery && do_pkey_ctx_init(pkctx, sigopts); 2234*b077aed3SPierre Pronchery } 2235*b077aed3SPierre Pronchery 2236*b077aed3SPierre Pronchery static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx, 2237*b077aed3SPierre Pronchery const char *name, const char *value, int add_default) 2238*b077aed3SPierre Pronchery { 2239*b077aed3SPierre Pronchery const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); 2240*b077aed3SPierre Pronchery X509_EXTENSION *new_ext = X509V3_EXT_nconf(NULL, ext_ctx, name, value); 2241*b077aed3SPierre Pronchery int idx, rv = 0; 2242*b077aed3SPierre Pronchery 2243*b077aed3SPierre Pronchery if (new_ext == NULL) 2244*b077aed3SPierre Pronchery return rv; 2245*b077aed3SPierre Pronchery 2246*b077aed3SPierre Pronchery idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1); 2247*b077aed3SPierre Pronchery if (idx >= 0) { 2248*b077aed3SPierre Pronchery X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx); 2249*b077aed3SPierre Pronchery ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext); 2250*b077aed3SPierre Pronchery int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */ 2251*b077aed3SPierre Pronchery 2252*b077aed3SPierre Pronchery if (disabled) { 2253*b077aed3SPierre Pronchery X509_delete_ext(cert, idx); 2254*b077aed3SPierre Pronchery X509_EXTENSION_free(found_ext); 2255*b077aed3SPierre Pronchery } /* else keep existing key identifier, which might be outdated */ 2256*b077aed3SPierre Pronchery rv = 1; 2257*b077aed3SPierre Pronchery } else { 2258*b077aed3SPierre Pronchery rv = !add_default || X509_add_ext(cert, new_ext, -1); 2259*b077aed3SPierre Pronchery } 2260*b077aed3SPierre Pronchery X509_EXTENSION_free(new_ext); 2261*b077aed3SPierre Pronchery return rv; 2262*b077aed3SPierre Pronchery } 2263*b077aed3SPierre Pronchery 2264*b077aed3SPierre Pronchery /* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */ 2265*b077aed3SPierre Pronchery int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md, 2266*b077aed3SPierre Pronchery STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx) 2267*b077aed3SPierre Pronchery { 2268*b077aed3SPierre Pronchery const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); 2269*b077aed3SPierre Pronchery EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 2270*b077aed3SPierre Pronchery int self_sign; 2271*b077aed3SPierre Pronchery int rv = 0; 2272*b077aed3SPierre Pronchery 2273*b077aed3SPierre Pronchery if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) { 2274*b077aed3SPierre Pronchery /* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */ 2275*b077aed3SPierre Pronchery if (!X509_set_version(cert, X509_VERSION_3)) 2276*b077aed3SPierre Pronchery goto end; 2277*b077aed3SPierre Pronchery 2278*b077aed3SPierre Pronchery /* 2279*b077aed3SPierre Pronchery * Add default SKID before such that default AKID can make use of it 2280*b077aed3SPierre Pronchery * in case the certificate is self-signed 2281*b077aed3SPierre Pronchery */ 2282*b077aed3SPierre Pronchery /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */ 2283*b077aed3SPierre Pronchery if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1)) 2284*b077aed3SPierre Pronchery goto end; 2285*b077aed3SPierre Pronchery /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */ 2286*b077aed3SPierre Pronchery ERR_set_mark(); 2287*b077aed3SPierre Pronchery self_sign = X509_check_private_key(cert, pkey); 2288*b077aed3SPierre Pronchery ERR_pop_to_mark(); 2289*b077aed3SPierre Pronchery if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier", 2290*b077aed3SPierre Pronchery "keyid, issuer", !self_sign)) 2291*b077aed3SPierre Pronchery goto end; 2292*b077aed3SPierre Pronchery } 2293*b077aed3SPierre Pronchery 2294*b077aed3SPierre Pronchery if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0) 2295*b077aed3SPierre Pronchery rv = (X509_sign_ctx(cert, mctx) > 0); 2296*b077aed3SPierre Pronchery end: 2297*b077aed3SPierre Pronchery EVP_MD_CTX_free(mctx); 2298*b077aed3SPierre Pronchery return rv; 2299*b077aed3SPierre Pronchery } 2300*b077aed3SPierre Pronchery 2301*b077aed3SPierre Pronchery /* Sign the certificate request info */ 2302*b077aed3SPierre Pronchery int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md, 2303*b077aed3SPierre Pronchery STACK_OF(OPENSSL_STRING) *sigopts) 2304*b077aed3SPierre Pronchery { 2305*b077aed3SPierre Pronchery int rv = 0; 2306*b077aed3SPierre Pronchery EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 2307*b077aed3SPierre Pronchery 2308*b077aed3SPierre Pronchery if (do_sign_init(mctx, pkey, md, sigopts) > 0) 2309*b077aed3SPierre Pronchery rv = (X509_REQ_sign_ctx(x, mctx) > 0); 2310*b077aed3SPierre Pronchery EVP_MD_CTX_free(mctx); 2311*b077aed3SPierre Pronchery return rv; 2312*b077aed3SPierre Pronchery } 2313*b077aed3SPierre Pronchery 2314*b077aed3SPierre Pronchery /* Sign the CRL info */ 2315*b077aed3SPierre Pronchery int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md, 2316*b077aed3SPierre Pronchery STACK_OF(OPENSSL_STRING) *sigopts) 2317*b077aed3SPierre Pronchery { 2318*b077aed3SPierre Pronchery int rv = 0; 2319*b077aed3SPierre Pronchery EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 2320*b077aed3SPierre Pronchery 2321*b077aed3SPierre Pronchery if (do_sign_init(mctx, pkey, md, sigopts) > 0) 2322*b077aed3SPierre Pronchery rv = (X509_CRL_sign_ctx(x, mctx) > 0); 2323*b077aed3SPierre Pronchery EVP_MD_CTX_free(mctx); 2324*b077aed3SPierre Pronchery return rv; 2325*b077aed3SPierre Pronchery } 2326*b077aed3SPierre Pronchery 2327*b077aed3SPierre Pronchery /* 2328*b077aed3SPierre Pronchery * do_X509_verify returns 1 if the signature is valid, 2329*b077aed3SPierre Pronchery * 0 if the signature check fails, or -1 if error occurs. 2330*b077aed3SPierre Pronchery */ 2331*b077aed3SPierre Pronchery int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts) 2332*b077aed3SPierre Pronchery { 2333*b077aed3SPierre Pronchery int rv = 0; 2334*b077aed3SPierre Pronchery 2335*b077aed3SPierre Pronchery if (do_x509_init(x, vfyopts) > 0) 2336*b077aed3SPierre Pronchery rv = X509_verify(x, pkey); 2337*b077aed3SPierre Pronchery else 2338*b077aed3SPierre Pronchery rv = -1; 2339*b077aed3SPierre Pronchery return rv; 2340*b077aed3SPierre Pronchery } 2341*b077aed3SPierre Pronchery 2342*b077aed3SPierre Pronchery /* 2343*b077aed3SPierre Pronchery * do_X509_REQ_verify returns 1 if the signature is valid, 2344*b077aed3SPierre Pronchery * 0 if the signature check fails, or -1 if error occurs. 2345*b077aed3SPierre Pronchery */ 2346*b077aed3SPierre Pronchery int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, 2347*b077aed3SPierre Pronchery STACK_OF(OPENSSL_STRING) *vfyopts) 2348*b077aed3SPierre Pronchery { 2349*b077aed3SPierre Pronchery int rv = 0; 2350*b077aed3SPierre Pronchery 2351*b077aed3SPierre Pronchery if (do_x509_req_init(x, vfyopts) > 0) 2352*b077aed3SPierre Pronchery rv = X509_REQ_verify_ex(x, pkey, 2353*b077aed3SPierre Pronchery app_get0_libctx(), app_get0_propq()); 2354*b077aed3SPierre Pronchery else 2355*b077aed3SPierre Pronchery rv = -1; 2356*b077aed3SPierre Pronchery return rv; 2357*b077aed3SPierre Pronchery } 2358*b077aed3SPierre Pronchery 2359*b077aed3SPierre Pronchery /* Get first http URL from a DIST_POINT structure */ 2360*b077aed3SPierre Pronchery 2361*b077aed3SPierre Pronchery static const char *get_dp_url(DIST_POINT *dp) 2362*b077aed3SPierre Pronchery { 2363*b077aed3SPierre Pronchery GENERAL_NAMES *gens; 2364*b077aed3SPierre Pronchery GENERAL_NAME *gen; 2365*b077aed3SPierre Pronchery int i, gtype; 2366*b077aed3SPierre Pronchery ASN1_STRING *uri; 2367*b077aed3SPierre Pronchery if (!dp->distpoint || dp->distpoint->type != 0) 2368*b077aed3SPierre Pronchery return NULL; 2369*b077aed3SPierre Pronchery gens = dp->distpoint->name.fullname; 2370*b077aed3SPierre Pronchery for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 2371*b077aed3SPierre Pronchery gen = sk_GENERAL_NAME_value(gens, i); 2372*b077aed3SPierre Pronchery uri = GENERAL_NAME_get0_value(gen, >ype); 2373*b077aed3SPierre Pronchery if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { 2374*b077aed3SPierre Pronchery const char *uptr = (const char *)ASN1_STRING_get0_data(uri); 2375*b077aed3SPierre Pronchery 2376*b077aed3SPierre Pronchery if (IS_HTTP(uptr)) /* can/should not use HTTPS here */ 2377*b077aed3SPierre Pronchery return uptr; 2378*b077aed3SPierre Pronchery } 2379*b077aed3SPierre Pronchery } 2380*b077aed3SPierre Pronchery return NULL; 2381*b077aed3SPierre Pronchery } 2382*b077aed3SPierre Pronchery 2383*b077aed3SPierre Pronchery /* 2384*b077aed3SPierre Pronchery * Look through a CRLDP structure and attempt to find an http URL to 2385*b077aed3SPierre Pronchery * downloads a CRL from. 2386*b077aed3SPierre Pronchery */ 2387*b077aed3SPierre Pronchery 2388*b077aed3SPierre Pronchery static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) 2389*b077aed3SPierre Pronchery { 2390*b077aed3SPierre Pronchery int i; 2391*b077aed3SPierre Pronchery const char *urlptr = NULL; 2392*b077aed3SPierre Pronchery for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { 2393*b077aed3SPierre Pronchery DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); 2394*b077aed3SPierre Pronchery urlptr = get_dp_url(dp); 2395*b077aed3SPierre Pronchery if (urlptr != NULL) 2396*b077aed3SPierre Pronchery return load_crl(urlptr, FORMAT_UNDEF, 0, "CRL via CDP"); 2397*b077aed3SPierre Pronchery } 2398*b077aed3SPierre Pronchery return NULL; 2399*b077aed3SPierre Pronchery } 2400*b077aed3SPierre Pronchery 2401*b077aed3SPierre Pronchery /* 2402*b077aed3SPierre Pronchery * Example of downloading CRLs from CRLDP: 2403*b077aed3SPierre Pronchery * not usable for real world as it always downloads and doesn't cache anything. 2404*b077aed3SPierre Pronchery */ 2405*b077aed3SPierre Pronchery 2406*b077aed3SPierre Pronchery static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *ctx, 2407*b077aed3SPierre Pronchery const X509_NAME *nm) 2408*b077aed3SPierre Pronchery { 2409*b077aed3SPierre Pronchery X509 *x; 2410*b077aed3SPierre Pronchery STACK_OF(X509_CRL) *crls = NULL; 2411*b077aed3SPierre Pronchery X509_CRL *crl; 2412*b077aed3SPierre Pronchery STACK_OF(DIST_POINT) *crldp; 2413*b077aed3SPierre Pronchery 2414*b077aed3SPierre Pronchery crls = sk_X509_CRL_new_null(); 2415*b077aed3SPierre Pronchery if (!crls) 2416*b077aed3SPierre Pronchery return NULL; 2417*b077aed3SPierre Pronchery x = X509_STORE_CTX_get_current_cert(ctx); 2418*b077aed3SPierre Pronchery crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); 2419*b077aed3SPierre Pronchery crl = load_crl_crldp(crldp); 2420*b077aed3SPierre Pronchery sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); 2421*b077aed3SPierre Pronchery if (!crl) { 2422*b077aed3SPierre Pronchery sk_X509_CRL_free(crls); 2423*b077aed3SPierre Pronchery return NULL; 2424*b077aed3SPierre Pronchery } 2425*b077aed3SPierre Pronchery sk_X509_CRL_push(crls, crl); 2426*b077aed3SPierre Pronchery /* Try to download delta CRL */ 2427*b077aed3SPierre Pronchery crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); 2428*b077aed3SPierre Pronchery crl = load_crl_crldp(crldp); 2429*b077aed3SPierre Pronchery sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); 2430*b077aed3SPierre Pronchery if (crl) 2431*b077aed3SPierre Pronchery sk_X509_CRL_push(crls, crl); 2432*b077aed3SPierre Pronchery return crls; 2433*b077aed3SPierre Pronchery } 2434*b077aed3SPierre Pronchery 2435*b077aed3SPierre Pronchery void store_setup_crl_download(X509_STORE *st) 2436*b077aed3SPierre Pronchery { 2437*b077aed3SPierre Pronchery X509_STORE_set_lookup_crls_cb(st, crls_http_cb); 2438*b077aed3SPierre Pronchery } 2439*b077aed3SPierre Pronchery 2440*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_SOCK 2441*b077aed3SPierre Pronchery static const char *tls_error_hint(void) 2442*b077aed3SPierre Pronchery { 2443*b077aed3SPierre Pronchery unsigned long err = ERR_peek_error(); 2444*b077aed3SPierre Pronchery 2445*b077aed3SPierre Pronchery if (ERR_GET_LIB(err) != ERR_LIB_SSL) 2446*b077aed3SPierre Pronchery err = ERR_peek_last_error(); 2447*b077aed3SPierre Pronchery if (ERR_GET_LIB(err) != ERR_LIB_SSL) 2448*b077aed3SPierre Pronchery return NULL; 2449*b077aed3SPierre Pronchery 2450*b077aed3SPierre Pronchery switch (ERR_GET_REASON(err)) { 2451*b077aed3SPierre Pronchery case SSL_R_WRONG_VERSION_NUMBER: 2452*b077aed3SPierre Pronchery return "The server does not support (a suitable version of) TLS"; 2453*b077aed3SPierre Pronchery case SSL_R_UNKNOWN_PROTOCOL: 2454*b077aed3SPierre Pronchery return "The server does not support HTTPS"; 2455*b077aed3SPierre Pronchery case SSL_R_CERTIFICATE_VERIFY_FAILED: 2456*b077aed3SPierre Pronchery return "Cannot authenticate server via its TLS certificate, likely due to mismatch with our trusted TLS certs or missing revocation status"; 2457*b077aed3SPierre Pronchery case SSL_AD_REASON_OFFSET + TLS1_AD_UNKNOWN_CA: 2458*b077aed3SPierre Pronchery return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status"; 2459*b077aed3SPierre Pronchery case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE: 2460*b077aed3SPierre Pronchery return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it"; 2461*b077aed3SPierre Pronchery default: /* no error or no hint available for error */ 2462*b077aed3SPierre Pronchery return NULL; 2463*b077aed3SPierre Pronchery } 2464*b077aed3SPierre Pronchery } 2465*b077aed3SPierre Pronchery 2466*b077aed3SPierre Pronchery /* HTTP callback function that supports TLS connection also via HTTPS proxy */ 2467*b077aed3SPierre Pronchery BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail) 2468*b077aed3SPierre Pronchery { 2469*b077aed3SPierre Pronchery APP_HTTP_TLS_INFO *info = (APP_HTTP_TLS_INFO *)arg; 2470*b077aed3SPierre Pronchery SSL_CTX *ssl_ctx = info->ssl_ctx; 2471*b077aed3SPierre Pronchery 2472*b077aed3SPierre Pronchery if (ssl_ctx == NULL) /* not using TLS */ 2473*b077aed3SPierre Pronchery return bio; 2474*b077aed3SPierre Pronchery if (connect) { 2475*b077aed3SPierre Pronchery SSL *ssl; 2476*b077aed3SPierre Pronchery BIO *sbio = NULL; 2477*b077aed3SPierre Pronchery X509_STORE *ts = SSL_CTX_get_cert_store(ssl_ctx); 2478*b077aed3SPierre Pronchery X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts); 2479*b077aed3SPierre Pronchery const char *host = vpm == NULL ? NULL : 2480*b077aed3SPierre Pronchery X509_VERIFY_PARAM_get0_host(vpm, 0 /* first hostname */); 2481*b077aed3SPierre Pronchery 2482*b077aed3SPierre Pronchery /* adapt after fixing callback design flaw, see #17088 */ 2483*b077aed3SPierre Pronchery if ((info->use_proxy 2484*b077aed3SPierre Pronchery && !OSSL_HTTP_proxy_connect(bio, info->server, info->port, 2485*b077aed3SPierre Pronchery NULL, NULL, /* no proxy credentials */ 2486*b077aed3SPierre Pronchery info->timeout, bio_err, opt_getprog())) 2487*b077aed3SPierre Pronchery || (sbio = BIO_new(BIO_f_ssl())) == NULL) { 2488*b077aed3SPierre Pronchery return NULL; 2489*b077aed3SPierre Pronchery } 2490*b077aed3SPierre Pronchery if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) { 2491*b077aed3SPierre Pronchery BIO_free(sbio); 2492*b077aed3SPierre Pronchery return NULL; 2493*b077aed3SPierre Pronchery } 2494*b077aed3SPierre Pronchery 2495*b077aed3SPierre Pronchery if (vpm != NULL) 2496*b077aed3SPierre Pronchery SSL_set_tlsext_host_name(ssl, host /* may be NULL */); 2497*b077aed3SPierre Pronchery 2498*b077aed3SPierre Pronchery SSL_set_connect_state(ssl); 2499*b077aed3SPierre Pronchery BIO_set_ssl(sbio, ssl, BIO_CLOSE); 2500*b077aed3SPierre Pronchery 2501*b077aed3SPierre Pronchery bio = BIO_push(sbio, bio); 2502*b077aed3SPierre Pronchery } 2503*b077aed3SPierre Pronchery if (!connect) { 2504*b077aed3SPierre Pronchery const char *hint; 2505*b077aed3SPierre Pronchery BIO *cbio; 2506*b077aed3SPierre Pronchery 2507*b077aed3SPierre Pronchery if (!detail) { /* disconnecting after error */ 2508*b077aed3SPierre Pronchery hint = tls_error_hint(); 2509*b077aed3SPierre Pronchery if (hint != NULL) 2510*b077aed3SPierre Pronchery ERR_add_error_data(2, " : ", hint); 2511*b077aed3SPierre Pronchery } 2512*b077aed3SPierre Pronchery if (ssl_ctx != NULL) { 2513*b077aed3SPierre Pronchery (void)ERR_set_mark(); 2514*b077aed3SPierre Pronchery BIO_ssl_shutdown(bio); 2515*b077aed3SPierre Pronchery cbio = BIO_pop(bio); /* connect+HTTP BIO */ 2516*b077aed3SPierre Pronchery BIO_free(bio); /* SSL BIO */ 2517*b077aed3SPierre Pronchery (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */ 2518*b077aed3SPierre Pronchery bio = cbio; 2519*b077aed3SPierre Pronchery } 2520*b077aed3SPierre Pronchery } 2521*b077aed3SPierre Pronchery return bio; 2522*b077aed3SPierre Pronchery } 2523*b077aed3SPierre Pronchery 2524*b077aed3SPierre Pronchery void APP_HTTP_TLS_INFO_free(APP_HTTP_TLS_INFO *info) 2525*b077aed3SPierre Pronchery { 2526*b077aed3SPierre Pronchery if (info != NULL) { 2527*b077aed3SPierre Pronchery SSL_CTX_free(info->ssl_ctx); 2528*b077aed3SPierre Pronchery OPENSSL_free(info); 2529*b077aed3SPierre Pronchery } 2530*b077aed3SPierre Pronchery } 2531*b077aed3SPierre Pronchery 2532*b077aed3SPierre Pronchery ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy, 2533*b077aed3SPierre Pronchery const char *no_proxy, SSL_CTX *ssl_ctx, 2534*b077aed3SPierre Pronchery const STACK_OF(CONF_VALUE) *headers, 2535*b077aed3SPierre Pronchery long timeout, const char *expected_content_type, 2536*b077aed3SPierre Pronchery const ASN1_ITEM *it) 2537*b077aed3SPierre Pronchery { 2538*b077aed3SPierre Pronchery APP_HTTP_TLS_INFO info; 2539*b077aed3SPierre Pronchery char *server; 2540*b077aed3SPierre Pronchery char *port; 2541*b077aed3SPierre Pronchery int use_ssl; 2542*b077aed3SPierre Pronchery BIO *mem; 2543*b077aed3SPierre Pronchery ASN1_VALUE *resp = NULL; 2544*b077aed3SPierre Pronchery 2545*b077aed3SPierre Pronchery if (url == NULL || it == NULL) { 2546*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); 2547*b077aed3SPierre Pronchery return NULL; 2548*b077aed3SPierre Pronchery } 2549*b077aed3SPierre Pronchery 2550*b077aed3SPierre Pronchery if (!OSSL_HTTP_parse_url(url, &use_ssl, NULL /* userinfo */, &server, &port, 2551*b077aed3SPierre Pronchery NULL /* port_num, */, NULL, NULL, NULL)) 2552*b077aed3SPierre Pronchery return NULL; 2553*b077aed3SPierre Pronchery if (use_ssl && ssl_ctx == NULL) { 2554*b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER, 2555*b077aed3SPierre Pronchery "missing SSL_CTX"); 2556*b077aed3SPierre Pronchery goto end; 2557*b077aed3SPierre Pronchery } 2558*b077aed3SPierre Pronchery if (!use_ssl && ssl_ctx != NULL) { 2559*b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT, 2560*b077aed3SPierre Pronchery "SSL_CTX given but use_ssl == 0"); 2561*b077aed3SPierre Pronchery goto end; 2562*b077aed3SPierre Pronchery } 2563*b077aed3SPierre Pronchery 2564*b077aed3SPierre Pronchery info.server = server; 2565*b077aed3SPierre Pronchery info.port = port; 2566*b077aed3SPierre Pronchery info.use_proxy = /* workaround for callback design flaw, see #17088 */ 2567*b077aed3SPierre Pronchery OSSL_HTTP_adapt_proxy(proxy, no_proxy, server, use_ssl) != NULL; 2568*b077aed3SPierre Pronchery info.timeout = timeout; 2569*b077aed3SPierre Pronchery info.ssl_ctx = ssl_ctx; 2570*b077aed3SPierre Pronchery mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */, 2571*b077aed3SPierre Pronchery app_http_tls_cb, &info, 0 /* buf_size */, headers, 2572*b077aed3SPierre Pronchery expected_content_type, 1 /* expect_asn1 */, 2573*b077aed3SPierre Pronchery OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout); 2574*b077aed3SPierre Pronchery resp = ASN1_item_d2i_bio(it, mem, NULL); 2575*b077aed3SPierre Pronchery BIO_free(mem); 2576*b077aed3SPierre Pronchery 2577*b077aed3SPierre Pronchery end: 2578*b077aed3SPierre Pronchery OPENSSL_free(server); 2579*b077aed3SPierre Pronchery OPENSSL_free(port); 2580*b077aed3SPierre Pronchery return resp; 2581*b077aed3SPierre Pronchery 2582*b077aed3SPierre Pronchery } 2583*b077aed3SPierre Pronchery 2584*b077aed3SPierre Pronchery ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, 2585*b077aed3SPierre Pronchery const char *path, const char *proxy, 2586*b077aed3SPierre Pronchery const char *no_proxy, SSL_CTX *ssl_ctx, 2587*b077aed3SPierre Pronchery const STACK_OF(CONF_VALUE) *headers, 2588*b077aed3SPierre Pronchery const char *content_type, 2589*b077aed3SPierre Pronchery ASN1_VALUE *req, const ASN1_ITEM *req_it, 2590*b077aed3SPierre Pronchery const char *expected_content_type, 2591*b077aed3SPierre Pronchery long timeout, const ASN1_ITEM *rsp_it) 2592*b077aed3SPierre Pronchery { 2593*b077aed3SPierre Pronchery int use_ssl = ssl_ctx != NULL; 2594*b077aed3SPierre Pronchery APP_HTTP_TLS_INFO info; 2595*b077aed3SPierre Pronchery BIO *rsp, *req_mem = ASN1_item_i2d_mem_bio(req_it, req); 2596*b077aed3SPierre Pronchery ASN1_VALUE *res; 2597*b077aed3SPierre Pronchery 2598*b077aed3SPierre Pronchery if (req_mem == NULL) 2599*b077aed3SPierre Pronchery return NULL; 2600*b077aed3SPierre Pronchery 2601*b077aed3SPierre Pronchery info.server = host; 2602*b077aed3SPierre Pronchery info.port = port; 2603*b077aed3SPierre Pronchery info.use_proxy = /* workaround for callback design flaw, see #17088 */ 2604*b077aed3SPierre Pronchery OSSL_HTTP_adapt_proxy(proxy, no_proxy, host, use_ssl) != NULL; 2605*b077aed3SPierre Pronchery info.timeout = timeout; 2606*b077aed3SPierre Pronchery info.ssl_ctx = ssl_ctx; 2607*b077aed3SPierre Pronchery rsp = OSSL_HTTP_transfer(NULL, host, port, path, use_ssl, 2608*b077aed3SPierre Pronchery proxy, no_proxy, NULL /* bio */, NULL /* rbio */, 2609*b077aed3SPierre Pronchery app_http_tls_cb, &info, 2610*b077aed3SPierre Pronchery 0 /* buf_size */, headers, content_type, req_mem, 2611*b077aed3SPierre Pronchery expected_content_type, 1 /* expect_asn1 */, 2612*b077aed3SPierre Pronchery OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout, 2613*b077aed3SPierre Pronchery 0 /* keep_alive */); 2614*b077aed3SPierre Pronchery BIO_free(req_mem); 2615*b077aed3SPierre Pronchery res = ASN1_item_d2i_bio(rsp_it, rsp, NULL); 2616*b077aed3SPierre Pronchery BIO_free(rsp); 2617*b077aed3SPierre Pronchery return res; 2618*b077aed3SPierre Pronchery } 2619*b077aed3SPierre Pronchery 2620*b077aed3SPierre Pronchery #endif 2621*b077aed3SPierre Pronchery 2622*b077aed3SPierre Pronchery /* 2623*b077aed3SPierre Pronchery * Platform-specific sections 2624*b077aed3SPierre Pronchery */ 2625*b077aed3SPierre Pronchery #if defined(_WIN32) 2626*b077aed3SPierre Pronchery # ifdef fileno 2627*b077aed3SPierre Pronchery # undef fileno 2628*b077aed3SPierre Pronchery # define fileno(a) (int)_fileno(a) 2629*b077aed3SPierre Pronchery # endif 2630*b077aed3SPierre Pronchery 2631*b077aed3SPierre Pronchery # include <windows.h> 2632*b077aed3SPierre Pronchery # include <tchar.h> 2633*b077aed3SPierre Pronchery 2634*b077aed3SPierre Pronchery static int WIN32_rename(const char *from, const char *to) 2635*b077aed3SPierre Pronchery { 2636*b077aed3SPierre Pronchery TCHAR *tfrom = NULL, *tto; 2637*b077aed3SPierre Pronchery DWORD err; 2638*b077aed3SPierre Pronchery int ret = 0; 2639*b077aed3SPierre Pronchery 2640*b077aed3SPierre Pronchery if (sizeof(TCHAR) == 1) { 2641*b077aed3SPierre Pronchery tfrom = (TCHAR *)from; 2642*b077aed3SPierre Pronchery tto = (TCHAR *)to; 2643*b077aed3SPierre Pronchery } else { /* UNICODE path */ 2644*b077aed3SPierre Pronchery 2645*b077aed3SPierre Pronchery size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; 2646*b077aed3SPierre Pronchery tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); 2647*b077aed3SPierre Pronchery if (tfrom == NULL) 2648*b077aed3SPierre Pronchery goto err; 2649*b077aed3SPierre Pronchery tto = tfrom + flen; 2650*b077aed3SPierre Pronchery # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2651*b077aed3SPierre Pronchery if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) 2652*b077aed3SPierre Pronchery # endif 2653*b077aed3SPierre Pronchery for (i = 0; i < flen; i++) 2654*b077aed3SPierre Pronchery tfrom[i] = (TCHAR)from[i]; 2655*b077aed3SPierre Pronchery # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2656*b077aed3SPierre Pronchery if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) 2657*b077aed3SPierre Pronchery # endif 2658*b077aed3SPierre Pronchery for (i = 0; i < tlen; i++) 2659*b077aed3SPierre Pronchery tto[i] = (TCHAR)to[i]; 2660*b077aed3SPierre Pronchery } 2661*b077aed3SPierre Pronchery 2662*b077aed3SPierre Pronchery if (MoveFile(tfrom, tto)) 2663*b077aed3SPierre Pronchery goto ok; 2664*b077aed3SPierre Pronchery err = GetLastError(); 2665*b077aed3SPierre Pronchery if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { 2666*b077aed3SPierre Pronchery if (DeleteFile(tto) && MoveFile(tfrom, tto)) 2667*b077aed3SPierre Pronchery goto ok; 2668*b077aed3SPierre Pronchery err = GetLastError(); 2669*b077aed3SPierre Pronchery } 2670*b077aed3SPierre Pronchery if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) 2671*b077aed3SPierre Pronchery errno = ENOENT; 2672*b077aed3SPierre Pronchery else if (err == ERROR_ACCESS_DENIED) 2673*b077aed3SPierre Pronchery errno = EACCES; 2674*b077aed3SPierre Pronchery else 2675*b077aed3SPierre Pronchery errno = EINVAL; /* we could map more codes... */ 2676*b077aed3SPierre Pronchery err: 2677*b077aed3SPierre Pronchery ret = -1; 2678*b077aed3SPierre Pronchery ok: 2679*b077aed3SPierre Pronchery if (tfrom != NULL && tfrom != (TCHAR *)from) 2680*b077aed3SPierre Pronchery free(tfrom); 2681*b077aed3SPierre Pronchery return ret; 2682*b077aed3SPierre Pronchery } 2683*b077aed3SPierre Pronchery #endif 2684*b077aed3SPierre Pronchery 2685*b077aed3SPierre Pronchery /* app_tminterval section */ 2686*b077aed3SPierre Pronchery #if defined(_WIN32) 2687*b077aed3SPierre Pronchery double app_tminterval(int stop, int usertime) 2688*b077aed3SPierre Pronchery { 2689*b077aed3SPierre Pronchery FILETIME now; 2690*b077aed3SPierre Pronchery double ret = 0; 2691*b077aed3SPierre Pronchery static ULARGE_INTEGER tmstart; 2692*b077aed3SPierre Pronchery static int warning = 1; 2693*b077aed3SPierre Pronchery # ifdef _WIN32_WINNT 2694*b077aed3SPierre Pronchery static HANDLE proc = NULL; 2695*b077aed3SPierre Pronchery 2696*b077aed3SPierre Pronchery if (proc == NULL) { 2697*b077aed3SPierre Pronchery if (check_winnt()) 2698*b077aed3SPierre Pronchery proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 2699*b077aed3SPierre Pronchery GetCurrentProcessId()); 2700*b077aed3SPierre Pronchery if (proc == NULL) 2701*b077aed3SPierre Pronchery proc = (HANDLE) - 1; 2702*b077aed3SPierre Pronchery } 2703*b077aed3SPierre Pronchery 2704*b077aed3SPierre Pronchery if (usertime && proc != (HANDLE) - 1) { 2705*b077aed3SPierre Pronchery FILETIME junk; 2706*b077aed3SPierre Pronchery GetProcessTimes(proc, &junk, &junk, &junk, &now); 2707*b077aed3SPierre Pronchery } else 2708*b077aed3SPierre Pronchery # endif 2709*b077aed3SPierre Pronchery { 2710*b077aed3SPierre Pronchery SYSTEMTIME systime; 2711*b077aed3SPierre Pronchery 2712*b077aed3SPierre Pronchery if (usertime && warning) { 2713*b077aed3SPierre Pronchery BIO_printf(bio_err, "To get meaningful results, run " 2714*b077aed3SPierre Pronchery "this program on idle system.\n"); 2715*b077aed3SPierre Pronchery warning = 0; 2716*b077aed3SPierre Pronchery } 2717*b077aed3SPierre Pronchery GetSystemTime(&systime); 2718*b077aed3SPierre Pronchery SystemTimeToFileTime(&systime, &now); 2719*b077aed3SPierre Pronchery } 2720*b077aed3SPierre Pronchery 2721*b077aed3SPierre Pronchery if (stop == TM_START) { 2722*b077aed3SPierre Pronchery tmstart.u.LowPart = now.dwLowDateTime; 2723*b077aed3SPierre Pronchery tmstart.u.HighPart = now.dwHighDateTime; 2724*b077aed3SPierre Pronchery } else { 2725*b077aed3SPierre Pronchery ULARGE_INTEGER tmstop; 2726*b077aed3SPierre Pronchery 2727*b077aed3SPierre Pronchery tmstop.u.LowPart = now.dwLowDateTime; 2728*b077aed3SPierre Pronchery tmstop.u.HighPart = now.dwHighDateTime; 2729*b077aed3SPierre Pronchery 2730*b077aed3SPierre Pronchery ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; 2731*b077aed3SPierre Pronchery } 2732*b077aed3SPierre Pronchery 2733*b077aed3SPierre Pronchery return ret; 2734*b077aed3SPierre Pronchery } 2735*b077aed3SPierre Pronchery #elif defined(OPENSSL_SYS_VXWORKS) 2736*b077aed3SPierre Pronchery # include <time.h> 2737*b077aed3SPierre Pronchery 2738*b077aed3SPierre Pronchery double app_tminterval(int stop, int usertime) 2739*b077aed3SPierre Pronchery { 2740*b077aed3SPierre Pronchery double ret = 0; 2741*b077aed3SPierre Pronchery # ifdef CLOCK_REALTIME 2742*b077aed3SPierre Pronchery static struct timespec tmstart; 2743*b077aed3SPierre Pronchery struct timespec now; 2744*b077aed3SPierre Pronchery # else 2745*b077aed3SPierre Pronchery static unsigned long tmstart; 2746*b077aed3SPierre Pronchery unsigned long now; 2747*b077aed3SPierre Pronchery # endif 2748*b077aed3SPierre Pronchery static int warning = 1; 2749*b077aed3SPierre Pronchery 2750*b077aed3SPierre Pronchery if (usertime && warning) { 2751*b077aed3SPierre Pronchery BIO_printf(bio_err, "To get meaningful results, run " 2752*b077aed3SPierre Pronchery "this program on idle system.\n"); 2753*b077aed3SPierre Pronchery warning = 0; 2754*b077aed3SPierre Pronchery } 2755*b077aed3SPierre Pronchery # ifdef CLOCK_REALTIME 2756*b077aed3SPierre Pronchery clock_gettime(CLOCK_REALTIME, &now); 2757*b077aed3SPierre Pronchery if (stop == TM_START) 2758*b077aed3SPierre Pronchery tmstart = now; 2759*b077aed3SPierre Pronchery else 2760*b077aed3SPierre Pronchery ret = ((now.tv_sec + now.tv_nsec * 1e-9) 2761*b077aed3SPierre Pronchery - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); 2762*b077aed3SPierre Pronchery # else 2763*b077aed3SPierre Pronchery now = tickGet(); 2764*b077aed3SPierre Pronchery if (stop == TM_START) 2765*b077aed3SPierre Pronchery tmstart = now; 2766*b077aed3SPierre Pronchery else 2767*b077aed3SPierre Pronchery ret = (now - tmstart) / (double)sysClkRateGet(); 2768*b077aed3SPierre Pronchery # endif 2769*b077aed3SPierre Pronchery return ret; 2770*b077aed3SPierre Pronchery } 2771*b077aed3SPierre Pronchery 2772*b077aed3SPierre Pronchery #elif defined(_SC_CLK_TCK) /* by means of unistd.h */ 2773*b077aed3SPierre Pronchery # include <sys/times.h> 2774*b077aed3SPierre Pronchery 2775*b077aed3SPierre Pronchery double app_tminterval(int stop, int usertime) 2776*b077aed3SPierre Pronchery { 2777*b077aed3SPierre Pronchery double ret = 0; 2778*b077aed3SPierre Pronchery struct tms rus; 2779*b077aed3SPierre Pronchery clock_t now = times(&rus); 2780*b077aed3SPierre Pronchery static clock_t tmstart; 2781*b077aed3SPierre Pronchery 2782*b077aed3SPierre Pronchery if (usertime) 2783*b077aed3SPierre Pronchery now = rus.tms_utime; 2784*b077aed3SPierre Pronchery 2785*b077aed3SPierre Pronchery if (stop == TM_START) { 2786*b077aed3SPierre Pronchery tmstart = now; 2787*b077aed3SPierre Pronchery } else { 2788*b077aed3SPierre Pronchery long int tck = sysconf(_SC_CLK_TCK); 2789*b077aed3SPierre Pronchery ret = (now - tmstart) / (double)tck; 2790*b077aed3SPierre Pronchery } 2791*b077aed3SPierre Pronchery 2792*b077aed3SPierre Pronchery return ret; 2793*b077aed3SPierre Pronchery } 2794*b077aed3SPierre Pronchery 2795*b077aed3SPierre Pronchery #else 2796*b077aed3SPierre Pronchery # include <sys/time.h> 2797*b077aed3SPierre Pronchery # include <sys/resource.h> 2798*b077aed3SPierre Pronchery 2799*b077aed3SPierre Pronchery double app_tminterval(int stop, int usertime) 2800*b077aed3SPierre Pronchery { 2801*b077aed3SPierre Pronchery double ret = 0; 2802*b077aed3SPierre Pronchery struct rusage rus; 2803*b077aed3SPierre Pronchery struct timeval now; 2804*b077aed3SPierre Pronchery static struct timeval tmstart; 2805*b077aed3SPierre Pronchery 2806*b077aed3SPierre Pronchery if (usertime) 2807*b077aed3SPierre Pronchery getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; 2808*b077aed3SPierre Pronchery else 2809*b077aed3SPierre Pronchery gettimeofday(&now, NULL); 2810*b077aed3SPierre Pronchery 2811*b077aed3SPierre Pronchery if (stop == TM_START) 2812*b077aed3SPierre Pronchery tmstart = now; 2813*b077aed3SPierre Pronchery else 2814*b077aed3SPierre Pronchery ret = ((now.tv_sec + now.tv_usec * 1e-6) 2815*b077aed3SPierre Pronchery - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); 2816*b077aed3SPierre Pronchery 2817*b077aed3SPierre Pronchery return ret; 2818*b077aed3SPierre Pronchery } 2819*b077aed3SPierre Pronchery #endif 2820*b077aed3SPierre Pronchery 2821*b077aed3SPierre Pronchery int app_access(const char* name, int flag) 2822*b077aed3SPierre Pronchery { 2823*b077aed3SPierre Pronchery #ifdef _WIN32 2824*b077aed3SPierre Pronchery return _access(name, flag); 2825*b077aed3SPierre Pronchery #else 2826*b077aed3SPierre Pronchery return access(name, flag); 2827*b077aed3SPierre Pronchery #endif 2828*b077aed3SPierre Pronchery } 2829*b077aed3SPierre Pronchery 2830*b077aed3SPierre Pronchery int app_isdir(const char *name) 2831*b077aed3SPierre Pronchery { 2832*b077aed3SPierre Pronchery return opt_isdir(name); 2833*b077aed3SPierre Pronchery } 2834*b077aed3SPierre Pronchery 2835*b077aed3SPierre Pronchery /* raw_read|write section */ 2836*b077aed3SPierre Pronchery #if defined(__VMS) 2837*b077aed3SPierre Pronchery # include "vms_term_sock.h" 2838*b077aed3SPierre Pronchery static int stdin_sock = -1; 2839*b077aed3SPierre Pronchery 2840*b077aed3SPierre Pronchery static void close_stdin_sock(void) 2841*b077aed3SPierre Pronchery { 2842*b077aed3SPierre Pronchery TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); 2843*b077aed3SPierre Pronchery } 2844*b077aed3SPierre Pronchery 2845*b077aed3SPierre Pronchery int fileno_stdin(void) 2846*b077aed3SPierre Pronchery { 2847*b077aed3SPierre Pronchery if (stdin_sock == -1) { 2848*b077aed3SPierre Pronchery TerminalSocket(TERM_SOCK_CREATE, &stdin_sock); 2849*b077aed3SPierre Pronchery atexit(close_stdin_sock); 2850*b077aed3SPierre Pronchery } 2851*b077aed3SPierre Pronchery 2852*b077aed3SPierre Pronchery return stdin_sock; 2853*b077aed3SPierre Pronchery } 2854*b077aed3SPierre Pronchery #else 2855*b077aed3SPierre Pronchery int fileno_stdin(void) 2856*b077aed3SPierre Pronchery { 2857*b077aed3SPierre Pronchery return fileno(stdin); 2858*b077aed3SPierre Pronchery } 2859*b077aed3SPierre Pronchery #endif 2860*b077aed3SPierre Pronchery 2861*b077aed3SPierre Pronchery int fileno_stdout(void) 2862*b077aed3SPierre Pronchery { 2863*b077aed3SPierre Pronchery return fileno(stdout); 2864*b077aed3SPierre Pronchery } 2865*b077aed3SPierre Pronchery 2866*b077aed3SPierre Pronchery #if defined(_WIN32) && defined(STD_INPUT_HANDLE) 2867*b077aed3SPierre Pronchery int raw_read_stdin(void *buf, int siz) 2868*b077aed3SPierre Pronchery { 2869*b077aed3SPierre Pronchery DWORD n; 2870*b077aed3SPierre Pronchery if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) 2871*b077aed3SPierre Pronchery return n; 2872*b077aed3SPierre Pronchery else 2873*b077aed3SPierre Pronchery return -1; 2874*b077aed3SPierre Pronchery } 2875*b077aed3SPierre Pronchery #elif defined(__VMS) 2876*b077aed3SPierre Pronchery # include <sys/socket.h> 2877*b077aed3SPierre Pronchery 2878*b077aed3SPierre Pronchery int raw_read_stdin(void *buf, int siz) 2879*b077aed3SPierre Pronchery { 2880*b077aed3SPierre Pronchery return recv(fileno_stdin(), buf, siz, 0); 2881*b077aed3SPierre Pronchery } 2882*b077aed3SPierre Pronchery #else 2883*b077aed3SPierre Pronchery # if defined(__TANDEM) 2884*b077aed3SPierre Pronchery # if defined(OPENSSL_TANDEM_FLOSS) 2885*b077aed3SPierre Pronchery # include <floss.h(floss_read)> 2886*b077aed3SPierre Pronchery # endif 2887*b077aed3SPierre Pronchery # endif 2888*b077aed3SPierre Pronchery int raw_read_stdin(void *buf, int siz) 2889*b077aed3SPierre Pronchery { 2890*b077aed3SPierre Pronchery return read(fileno_stdin(), buf, siz); 2891*b077aed3SPierre Pronchery } 2892*b077aed3SPierre Pronchery #endif 2893*b077aed3SPierre Pronchery 2894*b077aed3SPierre Pronchery #if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) 2895*b077aed3SPierre Pronchery int raw_write_stdout(const void *buf, int siz) 2896*b077aed3SPierre Pronchery { 2897*b077aed3SPierre Pronchery DWORD n; 2898*b077aed3SPierre Pronchery if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) 2899*b077aed3SPierre Pronchery return n; 2900*b077aed3SPierre Pronchery else 2901*b077aed3SPierre Pronchery return -1; 2902*b077aed3SPierre Pronchery } 2903*b077aed3SPierre Pronchery #elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) && defined(_SPT_MODEL_) 2904*b077aed3SPierre Pronchery # if defined(__TANDEM) 2905*b077aed3SPierre Pronchery # if defined(OPENSSL_TANDEM_FLOSS) 2906*b077aed3SPierre Pronchery # include <floss.h(floss_write)> 2907*b077aed3SPierre Pronchery # endif 2908*b077aed3SPierre Pronchery # endif 2909*b077aed3SPierre Pronchery int raw_write_stdout(const void *buf,int siz) 2910*b077aed3SPierre Pronchery { 2911*b077aed3SPierre Pronchery return write(fileno(stdout),(void*)buf,siz); 2912*b077aed3SPierre Pronchery } 2913*b077aed3SPierre Pronchery #else 2914*b077aed3SPierre Pronchery # if defined(__TANDEM) 2915*b077aed3SPierre Pronchery # if defined(OPENSSL_TANDEM_FLOSS) 2916*b077aed3SPierre Pronchery # include <floss.h(floss_write)> 2917*b077aed3SPierre Pronchery # endif 2918*b077aed3SPierre Pronchery # endif 2919*b077aed3SPierre Pronchery int raw_write_stdout(const void *buf, int siz) 2920*b077aed3SPierre Pronchery { 2921*b077aed3SPierre Pronchery return write(fileno_stdout(), buf, siz); 2922*b077aed3SPierre Pronchery } 2923*b077aed3SPierre Pronchery #endif 2924*b077aed3SPierre Pronchery 2925*b077aed3SPierre Pronchery /* 2926*b077aed3SPierre Pronchery * Centralized handling of input and output files with format specification 2927*b077aed3SPierre Pronchery * The format is meant to show what the input and output is supposed to be, 2928*b077aed3SPierre Pronchery * and is therefore a show of intent more than anything else. However, it 2929*b077aed3SPierre Pronchery * does impact behavior on some platforms, such as differentiating between 2930*b077aed3SPierre Pronchery * text and binary input/output on non-Unix platforms 2931*b077aed3SPierre Pronchery */ 2932*b077aed3SPierre Pronchery BIO *dup_bio_in(int format) 2933*b077aed3SPierre Pronchery { 2934*b077aed3SPierre Pronchery return BIO_new_fp(stdin, 2935*b077aed3SPierre Pronchery BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); 2936*b077aed3SPierre Pronchery } 2937*b077aed3SPierre Pronchery 2938*b077aed3SPierre Pronchery BIO *dup_bio_out(int format) 2939*b077aed3SPierre Pronchery { 2940*b077aed3SPierre Pronchery BIO *b = BIO_new_fp(stdout, 2941*b077aed3SPierre Pronchery BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); 2942*b077aed3SPierre Pronchery void *prefix = NULL; 2943*b077aed3SPierre Pronchery 2944*b077aed3SPierre Pronchery if (b == NULL) 2945*b077aed3SPierre Pronchery return NULL; 2946*b077aed3SPierre Pronchery 2947*b077aed3SPierre Pronchery #ifdef OPENSSL_SYS_VMS 2948*b077aed3SPierre Pronchery if (FMT_istext(format)) 2949*b077aed3SPierre Pronchery b = BIO_push(BIO_new(BIO_f_linebuffer()), b); 2950*b077aed3SPierre Pronchery #endif 2951*b077aed3SPierre Pronchery 2952*b077aed3SPierre Pronchery if (FMT_istext(format) 2953*b077aed3SPierre Pronchery && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { 2954*b077aed3SPierre Pronchery b = BIO_push(BIO_new(BIO_f_prefix()), b); 2955*b077aed3SPierre Pronchery BIO_set_prefix(b, prefix); 2956*b077aed3SPierre Pronchery } 2957*b077aed3SPierre Pronchery 2958*b077aed3SPierre Pronchery return b; 2959*b077aed3SPierre Pronchery } 2960*b077aed3SPierre Pronchery 2961*b077aed3SPierre Pronchery BIO *dup_bio_err(int format) 2962*b077aed3SPierre Pronchery { 2963*b077aed3SPierre Pronchery BIO *b = BIO_new_fp(stderr, 2964*b077aed3SPierre Pronchery BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0)); 2965*b077aed3SPierre Pronchery #ifdef OPENSSL_SYS_VMS 2966*b077aed3SPierre Pronchery if (b != NULL && FMT_istext(format)) 2967*b077aed3SPierre Pronchery b = BIO_push(BIO_new(BIO_f_linebuffer()), b); 2968*b077aed3SPierre Pronchery #endif 2969*b077aed3SPierre Pronchery return b; 2970*b077aed3SPierre Pronchery } 2971*b077aed3SPierre Pronchery 2972*b077aed3SPierre Pronchery void unbuffer(FILE *fp) 2973*b077aed3SPierre Pronchery { 2974*b077aed3SPierre Pronchery /* 2975*b077aed3SPierre Pronchery * On VMS, setbuf() will only take 32-bit pointers, and a compilation 2976*b077aed3SPierre Pronchery * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. 2977*b077aed3SPierre Pronchery * However, we trust that the C RTL will never give us a FILE pointer 2978*b077aed3SPierre Pronchery * above the first 4 GB of memory, so we simply turn off the warning 2979*b077aed3SPierre Pronchery * temporarily. 2980*b077aed3SPierre Pronchery */ 2981*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_VMS) && defined(__DECC) 2982*b077aed3SPierre Pronchery # pragma environment save 2983*b077aed3SPierre Pronchery # pragma message disable maylosedata2 2984*b077aed3SPierre Pronchery #endif 2985*b077aed3SPierre Pronchery setbuf(fp, NULL); 2986*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_VMS) && defined(__DECC) 2987*b077aed3SPierre Pronchery # pragma environment restore 2988*b077aed3SPierre Pronchery #endif 2989*b077aed3SPierre Pronchery } 2990*b077aed3SPierre Pronchery 2991*b077aed3SPierre Pronchery static const char *modestr(char mode, int format) 2992*b077aed3SPierre Pronchery { 2993*b077aed3SPierre Pronchery OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); 2994*b077aed3SPierre Pronchery 2995*b077aed3SPierre Pronchery switch (mode) { 2996*b077aed3SPierre Pronchery case 'a': 2997*b077aed3SPierre Pronchery return FMT_istext(format) ? "a" : "ab"; 2998*b077aed3SPierre Pronchery case 'r': 2999*b077aed3SPierre Pronchery return FMT_istext(format) ? "r" : "rb"; 3000*b077aed3SPierre Pronchery case 'w': 3001*b077aed3SPierre Pronchery return FMT_istext(format) ? "w" : "wb"; 3002*b077aed3SPierre Pronchery } 3003*b077aed3SPierre Pronchery /* The assert above should make sure we never reach this point */ 3004*b077aed3SPierre Pronchery return NULL; 3005*b077aed3SPierre Pronchery } 3006*b077aed3SPierre Pronchery 3007*b077aed3SPierre Pronchery static const char *modeverb(char mode) 3008*b077aed3SPierre Pronchery { 3009*b077aed3SPierre Pronchery switch (mode) { 3010*b077aed3SPierre Pronchery case 'a': 3011*b077aed3SPierre Pronchery return "appending"; 3012*b077aed3SPierre Pronchery case 'r': 3013*b077aed3SPierre Pronchery return "reading"; 3014*b077aed3SPierre Pronchery case 'w': 3015*b077aed3SPierre Pronchery return "writing"; 3016*b077aed3SPierre Pronchery } 3017*b077aed3SPierre Pronchery return "(doing something)"; 3018*b077aed3SPierre Pronchery } 3019*b077aed3SPierre Pronchery 3020*b077aed3SPierre Pronchery /* 3021*b077aed3SPierre Pronchery * Open a file for writing, owner-read-only. 3022*b077aed3SPierre Pronchery */ 3023*b077aed3SPierre Pronchery BIO *bio_open_owner(const char *filename, int format, int private) 3024*b077aed3SPierre Pronchery { 3025*b077aed3SPierre Pronchery FILE *fp = NULL; 3026*b077aed3SPierre Pronchery BIO *b = NULL; 3027*b077aed3SPierre Pronchery int textmode, bflags; 3028*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 3029*b077aed3SPierre Pronchery int fd = -1, mode; 3030*b077aed3SPierre Pronchery #endif 3031*b077aed3SPierre Pronchery 3032*b077aed3SPierre Pronchery if (!private || filename == NULL || strcmp(filename, "-") == 0) 3033*b077aed3SPierre Pronchery return bio_open_default(filename, 'w', format); 3034*b077aed3SPierre Pronchery 3035*b077aed3SPierre Pronchery textmode = FMT_istext(format); 3036*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 3037*b077aed3SPierre Pronchery mode = O_WRONLY; 3038*b077aed3SPierre Pronchery # ifdef O_CREAT 3039*b077aed3SPierre Pronchery mode |= O_CREAT; 3040*b077aed3SPierre Pronchery # endif 3041*b077aed3SPierre Pronchery # ifdef O_TRUNC 3042*b077aed3SPierre Pronchery mode |= O_TRUNC; 3043*b077aed3SPierre Pronchery # endif 3044*b077aed3SPierre Pronchery if (!textmode) { 3045*b077aed3SPierre Pronchery # ifdef O_BINARY 3046*b077aed3SPierre Pronchery mode |= O_BINARY; 3047*b077aed3SPierre Pronchery # elif defined(_O_BINARY) 3048*b077aed3SPierre Pronchery mode |= _O_BINARY; 3049*b077aed3SPierre Pronchery # endif 3050*b077aed3SPierre Pronchery } 3051*b077aed3SPierre Pronchery 3052*b077aed3SPierre Pronchery # ifdef OPENSSL_SYS_VMS 3053*b077aed3SPierre Pronchery /* VMS doesn't have O_BINARY, it just doesn't make sense. But, 3054*b077aed3SPierre Pronchery * it still needs to know that we're going binary, or fdopen() 3055*b077aed3SPierre Pronchery * will fail with "invalid argument"... so we tell VMS what the 3056*b077aed3SPierre Pronchery * context is. 3057*b077aed3SPierre Pronchery */ 3058*b077aed3SPierre Pronchery if (!textmode) 3059*b077aed3SPierre Pronchery fd = open(filename, mode, 0600, "ctx=bin"); 3060*b077aed3SPierre Pronchery else 3061*b077aed3SPierre Pronchery # endif 3062*b077aed3SPierre Pronchery fd = open(filename, mode, 0600); 3063*b077aed3SPierre Pronchery if (fd < 0) 3064*b077aed3SPierre Pronchery goto err; 3065*b077aed3SPierre Pronchery fp = fdopen(fd, modestr('w', format)); 3066*b077aed3SPierre Pronchery #else /* OPENSSL_NO_POSIX_IO */ 3067*b077aed3SPierre Pronchery /* Have stdio but not Posix IO, do the best we can */ 3068*b077aed3SPierre Pronchery fp = fopen(filename, modestr('w', format)); 3069*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_POSIX_IO */ 3070*b077aed3SPierre Pronchery if (fp == NULL) 3071*b077aed3SPierre Pronchery goto err; 3072*b077aed3SPierre Pronchery bflags = BIO_CLOSE; 3073*b077aed3SPierre Pronchery if (textmode) 3074*b077aed3SPierre Pronchery bflags |= BIO_FP_TEXT; 3075*b077aed3SPierre Pronchery b = BIO_new_fp(fp, bflags); 3076*b077aed3SPierre Pronchery if (b != NULL) 3077*b077aed3SPierre Pronchery return b; 3078*b077aed3SPierre Pronchery 3079*b077aed3SPierre Pronchery err: 3080*b077aed3SPierre Pronchery BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", 3081*b077aed3SPierre Pronchery opt_getprog(), filename, strerror(errno)); 3082*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 3083*b077aed3SPierre Pronchery /* If we have fp, then fdopen took over fd, so don't close both. */ 3084*b077aed3SPierre Pronchery if (fp != NULL) 3085*b077aed3SPierre Pronchery fclose(fp); 3086*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO 3087*b077aed3SPierre Pronchery else if (fd >= 0) 3088*b077aed3SPierre Pronchery close(fd); 3089*b077aed3SPierre Pronchery #endif 3090*b077aed3SPierre Pronchery return NULL; 3091*b077aed3SPierre Pronchery } 3092*b077aed3SPierre Pronchery 3093*b077aed3SPierre Pronchery static BIO *bio_open_default_(const char *filename, char mode, int format, 3094*b077aed3SPierre Pronchery int quiet) 3095*b077aed3SPierre Pronchery { 3096*b077aed3SPierre Pronchery BIO *ret; 3097*b077aed3SPierre Pronchery 3098*b077aed3SPierre Pronchery if (filename == NULL || strcmp(filename, "-") == 0) { 3099*b077aed3SPierre Pronchery ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); 3100*b077aed3SPierre Pronchery if (quiet) { 3101*b077aed3SPierre Pronchery ERR_clear_error(); 3102*b077aed3SPierre Pronchery return ret; 3103*b077aed3SPierre Pronchery } 3104*b077aed3SPierre Pronchery if (ret != NULL) 3105*b077aed3SPierre Pronchery return ret; 3106*b077aed3SPierre Pronchery BIO_printf(bio_err, 3107*b077aed3SPierre Pronchery "Can't open %s, %s\n", 3108*b077aed3SPierre Pronchery mode == 'r' ? "stdin" : "stdout", strerror(errno)); 3109*b077aed3SPierre Pronchery } else { 3110*b077aed3SPierre Pronchery ret = BIO_new_file(filename, modestr(mode, format)); 3111*b077aed3SPierre Pronchery if (quiet) { 3112*b077aed3SPierre Pronchery ERR_clear_error(); 3113*b077aed3SPierre Pronchery return ret; 3114*b077aed3SPierre Pronchery } 3115*b077aed3SPierre Pronchery if (ret != NULL) 3116*b077aed3SPierre Pronchery return ret; 3117*b077aed3SPierre Pronchery BIO_printf(bio_err, 3118*b077aed3SPierre Pronchery "Can't open \"%s\" for %s, %s\n", 3119*b077aed3SPierre Pronchery filename, modeverb(mode), strerror(errno)); 3120*b077aed3SPierre Pronchery } 3121*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 3122*b077aed3SPierre Pronchery return NULL; 3123*b077aed3SPierre Pronchery } 3124*b077aed3SPierre Pronchery 3125*b077aed3SPierre Pronchery BIO *bio_open_default(const char *filename, char mode, int format) 3126*b077aed3SPierre Pronchery { 3127*b077aed3SPierre Pronchery return bio_open_default_(filename, mode, format, 0); 3128*b077aed3SPierre Pronchery } 3129*b077aed3SPierre Pronchery 3130*b077aed3SPierre Pronchery BIO *bio_open_default_quiet(const char *filename, char mode, int format) 3131*b077aed3SPierre Pronchery { 3132*b077aed3SPierre Pronchery return bio_open_default_(filename, mode, format, 1); 3133*b077aed3SPierre Pronchery } 3134*b077aed3SPierre Pronchery 3135*b077aed3SPierre Pronchery void wait_for_async(SSL *s) 3136*b077aed3SPierre Pronchery { 3137*b077aed3SPierre Pronchery /* On Windows select only works for sockets, so we simply don't wait */ 3138*b077aed3SPierre Pronchery #ifndef OPENSSL_SYS_WINDOWS 3139*b077aed3SPierre Pronchery int width = 0; 3140*b077aed3SPierre Pronchery fd_set asyncfds; 3141*b077aed3SPierre Pronchery OSSL_ASYNC_FD *fds; 3142*b077aed3SPierre Pronchery size_t numfds; 3143*b077aed3SPierre Pronchery size_t i; 3144*b077aed3SPierre Pronchery 3145*b077aed3SPierre Pronchery if (!SSL_get_all_async_fds(s, NULL, &numfds)) 3146*b077aed3SPierre Pronchery return; 3147*b077aed3SPierre Pronchery if (numfds == 0) 3148*b077aed3SPierre Pronchery return; 3149*b077aed3SPierre Pronchery fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); 3150*b077aed3SPierre Pronchery if (!SSL_get_all_async_fds(s, fds, &numfds)) { 3151*b077aed3SPierre Pronchery OPENSSL_free(fds); 3152*b077aed3SPierre Pronchery return; 3153*b077aed3SPierre Pronchery } 3154*b077aed3SPierre Pronchery 3155*b077aed3SPierre Pronchery FD_ZERO(&asyncfds); 3156*b077aed3SPierre Pronchery for (i = 0; i < numfds; i++) { 3157*b077aed3SPierre Pronchery if (width <= (int)fds[i]) 3158*b077aed3SPierre Pronchery width = (int)fds[i] + 1; 3159*b077aed3SPierre Pronchery openssl_fdset((int)fds[i], &asyncfds); 3160*b077aed3SPierre Pronchery } 3161*b077aed3SPierre Pronchery select(width, (void *)&asyncfds, NULL, NULL, NULL); 3162*b077aed3SPierre Pronchery OPENSSL_free(fds); 3163*b077aed3SPierre Pronchery #endif 3164*b077aed3SPierre Pronchery } 3165*b077aed3SPierre Pronchery 3166*b077aed3SPierre Pronchery /* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ 3167*b077aed3SPierre Pronchery #if defined(OPENSSL_SYS_MSDOS) 3168*b077aed3SPierre Pronchery int has_stdin_waiting(void) 3169*b077aed3SPierre Pronchery { 3170*b077aed3SPierre Pronchery # if defined(OPENSSL_SYS_WINDOWS) 3171*b077aed3SPierre Pronchery HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); 3172*b077aed3SPierre Pronchery DWORD events = 0; 3173*b077aed3SPierre Pronchery INPUT_RECORD inputrec; 3174*b077aed3SPierre Pronchery DWORD insize = 1; 3175*b077aed3SPierre Pronchery BOOL peeked; 3176*b077aed3SPierre Pronchery 3177*b077aed3SPierre Pronchery if (inhand == INVALID_HANDLE_VALUE) { 3178*b077aed3SPierre Pronchery return 0; 3179*b077aed3SPierre Pronchery } 3180*b077aed3SPierre Pronchery 3181*b077aed3SPierre Pronchery peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); 3182*b077aed3SPierre Pronchery if (!peeked) { 3183*b077aed3SPierre Pronchery /* Probably redirected input? _kbhit() does not work in this case */ 3184*b077aed3SPierre Pronchery if (!feof(stdin)) { 3185*b077aed3SPierre Pronchery return 1; 3186*b077aed3SPierre Pronchery } 3187*b077aed3SPierre Pronchery return 0; 3188*b077aed3SPierre Pronchery } 3189*b077aed3SPierre Pronchery # endif 3190*b077aed3SPierre Pronchery return _kbhit(); 3191*b077aed3SPierre Pronchery } 3192*b077aed3SPierre Pronchery #endif 3193*b077aed3SPierre Pronchery 3194*b077aed3SPierre Pronchery /* Corrupt a signature by modifying final byte */ 3195*b077aed3SPierre Pronchery void corrupt_signature(const ASN1_STRING *signature) 3196*b077aed3SPierre Pronchery { 3197*b077aed3SPierre Pronchery unsigned char *s = signature->data; 3198*b077aed3SPierre Pronchery s[signature->length - 1] ^= 0x1; 3199*b077aed3SPierre Pronchery } 3200*b077aed3SPierre Pronchery 3201*b077aed3SPierre Pronchery int set_cert_times(X509 *x, const char *startdate, const char *enddate, 3202*b077aed3SPierre Pronchery int days) 3203*b077aed3SPierre Pronchery { 3204*b077aed3SPierre Pronchery if (startdate == NULL || strcmp(startdate, "today") == 0) { 3205*b077aed3SPierre Pronchery if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) 3206*b077aed3SPierre Pronchery return 0; 3207*b077aed3SPierre Pronchery } else { 3208*b077aed3SPierre Pronchery if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) 3209*b077aed3SPierre Pronchery return 0; 3210*b077aed3SPierre Pronchery } 3211*b077aed3SPierre Pronchery if (enddate == NULL) { 3212*b077aed3SPierre Pronchery if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) 3213*b077aed3SPierre Pronchery == NULL) 3214*b077aed3SPierre Pronchery return 0; 3215*b077aed3SPierre Pronchery } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { 3216*b077aed3SPierre Pronchery return 0; 3217*b077aed3SPierre Pronchery } 3218*b077aed3SPierre Pronchery return 1; 3219*b077aed3SPierre Pronchery } 3220*b077aed3SPierre Pronchery 3221*b077aed3SPierre Pronchery int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate) 3222*b077aed3SPierre Pronchery { 3223*b077aed3SPierre Pronchery int ret = 0; 3224*b077aed3SPierre Pronchery ASN1_TIME *tm = ASN1_TIME_new(); 3225*b077aed3SPierre Pronchery 3226*b077aed3SPierre Pronchery if (tm == NULL) 3227*b077aed3SPierre Pronchery goto end; 3228*b077aed3SPierre Pronchery 3229*b077aed3SPierre Pronchery if (lastupdate == NULL) { 3230*b077aed3SPierre Pronchery if (X509_gmtime_adj(tm, 0) == NULL) 3231*b077aed3SPierre Pronchery goto end; 3232*b077aed3SPierre Pronchery } else { 3233*b077aed3SPierre Pronchery if (!ASN1_TIME_set_string_X509(tm, lastupdate)) 3234*b077aed3SPierre Pronchery goto end; 3235*b077aed3SPierre Pronchery } 3236*b077aed3SPierre Pronchery 3237*b077aed3SPierre Pronchery if (!X509_CRL_set1_lastUpdate(crl, tm)) 3238*b077aed3SPierre Pronchery goto end; 3239*b077aed3SPierre Pronchery 3240*b077aed3SPierre Pronchery ret = 1; 3241*b077aed3SPierre Pronchery end: 3242*b077aed3SPierre Pronchery ASN1_TIME_free(tm); 3243*b077aed3SPierre Pronchery return ret; 3244*b077aed3SPierre Pronchery } 3245*b077aed3SPierre Pronchery 3246*b077aed3SPierre Pronchery int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate, 3247*b077aed3SPierre Pronchery long days, long hours, long secs) 3248*b077aed3SPierre Pronchery { 3249*b077aed3SPierre Pronchery int ret = 0; 3250*b077aed3SPierre Pronchery ASN1_TIME *tm = ASN1_TIME_new(); 3251*b077aed3SPierre Pronchery 3252*b077aed3SPierre Pronchery if (tm == NULL) 3253*b077aed3SPierre Pronchery goto end; 3254*b077aed3SPierre Pronchery 3255*b077aed3SPierre Pronchery if (nextupdate == NULL) { 3256*b077aed3SPierre Pronchery if (X509_time_adj_ex(tm, days, hours * 60 * 60 + secs, NULL) == NULL) 3257*b077aed3SPierre Pronchery goto end; 3258*b077aed3SPierre Pronchery } else { 3259*b077aed3SPierre Pronchery if (!ASN1_TIME_set_string_X509(tm, nextupdate)) 3260*b077aed3SPierre Pronchery goto end; 3261*b077aed3SPierre Pronchery } 3262*b077aed3SPierre Pronchery 3263*b077aed3SPierre Pronchery if (!X509_CRL_set1_nextUpdate(crl, tm)) 3264*b077aed3SPierre Pronchery goto end; 3265*b077aed3SPierre Pronchery 3266*b077aed3SPierre Pronchery ret = 1; 3267*b077aed3SPierre Pronchery end: 3268*b077aed3SPierre Pronchery ASN1_TIME_free(tm); 3269*b077aed3SPierre Pronchery return ret; 3270*b077aed3SPierre Pronchery } 3271*b077aed3SPierre Pronchery 3272*b077aed3SPierre Pronchery void make_uppercase(char *string) 3273*b077aed3SPierre Pronchery { 3274*b077aed3SPierre Pronchery int i; 3275*b077aed3SPierre Pronchery 3276*b077aed3SPierre Pronchery for (i = 0; string[i] != '\0'; i++) 3277*b077aed3SPierre Pronchery string[i] = toupper((unsigned char)string[i]); 3278*b077aed3SPierre Pronchery } 3279*b077aed3SPierre Pronchery 3280*b077aed3SPierre Pronchery /* This function is defined here due to visibility of bio_err */ 3281*b077aed3SPierre Pronchery int opt_printf_stderr(const char *fmt, ...) 3282*b077aed3SPierre Pronchery { 3283*b077aed3SPierre Pronchery va_list ap; 3284*b077aed3SPierre Pronchery int ret; 3285*b077aed3SPierre Pronchery 3286*b077aed3SPierre Pronchery va_start(ap, fmt); 3287*b077aed3SPierre Pronchery ret = BIO_vprintf(bio_err, fmt, ap); 3288*b077aed3SPierre Pronchery va_end(ap); 3289*b077aed3SPierre Pronchery return ret; 3290*b077aed3SPierre Pronchery } 3291*b077aed3SPierre Pronchery 3292*b077aed3SPierre Pronchery OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts, 3293*b077aed3SPierre Pronchery const OSSL_PARAM *paramdefs) 3294*b077aed3SPierre Pronchery { 3295*b077aed3SPierre Pronchery OSSL_PARAM *params = NULL; 3296*b077aed3SPierre Pronchery size_t sz = (size_t)sk_OPENSSL_STRING_num(opts); 3297*b077aed3SPierre Pronchery size_t params_n; 3298*b077aed3SPierre Pronchery char *opt = "", *stmp, *vtmp = NULL; 3299*b077aed3SPierre Pronchery int found = 1; 3300*b077aed3SPierre Pronchery 3301*b077aed3SPierre Pronchery if (opts == NULL) 3302*b077aed3SPierre Pronchery return NULL; 3303*b077aed3SPierre Pronchery 3304*b077aed3SPierre Pronchery params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1)); 3305*b077aed3SPierre Pronchery if (params == NULL) 3306*b077aed3SPierre Pronchery return NULL; 3307*b077aed3SPierre Pronchery 3308*b077aed3SPierre Pronchery for (params_n = 0; params_n < sz; params_n++) { 3309*b077aed3SPierre Pronchery opt = sk_OPENSSL_STRING_value(opts, (int)params_n); 3310*b077aed3SPierre Pronchery if ((stmp = OPENSSL_strdup(opt)) == NULL 3311*b077aed3SPierre Pronchery || (vtmp = strchr(stmp, ':')) == NULL) 3312*b077aed3SPierre Pronchery goto err; 3313*b077aed3SPierre Pronchery /* Replace ':' with 0 to terminate the string pointed to by stmp */ 3314*b077aed3SPierre Pronchery *vtmp = 0; 3315*b077aed3SPierre Pronchery /* Skip over the separator so that vmtp points to the value */ 3316*b077aed3SPierre Pronchery vtmp++; 3317*b077aed3SPierre Pronchery if (!OSSL_PARAM_allocate_from_text(¶ms[params_n], paramdefs, 3318*b077aed3SPierre Pronchery stmp, vtmp, strlen(vtmp), &found)) 3319*b077aed3SPierre Pronchery goto err; 3320*b077aed3SPierre Pronchery OPENSSL_free(stmp); 3321*b077aed3SPierre Pronchery } 3322*b077aed3SPierre Pronchery params[params_n] = OSSL_PARAM_construct_end(); 3323*b077aed3SPierre Pronchery return params; 3324*b077aed3SPierre Pronchery err: 3325*b077aed3SPierre Pronchery OPENSSL_free(stmp); 3326*b077aed3SPierre Pronchery BIO_printf(bio_err, "Parameter %s '%s'\n", found ? "error" : "unknown", 3327*b077aed3SPierre Pronchery opt); 3328*b077aed3SPierre Pronchery ERR_print_errors(bio_err); 3329*b077aed3SPierre Pronchery app_params_free(params); 3330*b077aed3SPierre Pronchery return NULL; 3331*b077aed3SPierre Pronchery } 3332*b077aed3SPierre Pronchery 3333*b077aed3SPierre Pronchery void app_params_free(OSSL_PARAM *params) 3334*b077aed3SPierre Pronchery { 3335*b077aed3SPierre Pronchery int i; 3336*b077aed3SPierre Pronchery 3337*b077aed3SPierre Pronchery if (params != NULL) { 3338*b077aed3SPierre Pronchery for (i = 0; params[i].key != NULL; ++i) 3339*b077aed3SPierre Pronchery OPENSSL_free(params[i].data); 3340*b077aed3SPierre Pronchery OPENSSL_free(params); 3341*b077aed3SPierre Pronchery } 3342*b077aed3SPierre Pronchery } 3343*b077aed3SPierre Pronchery 3344*b077aed3SPierre Pronchery EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose) 3345*b077aed3SPierre Pronchery { 3346*b077aed3SPierre Pronchery EVP_PKEY *res = NULL; 3347*b077aed3SPierre Pronchery 3348*b077aed3SPierre Pronchery if (verbose && alg != NULL) { 3349*b077aed3SPierre Pronchery BIO_printf(bio_err, "Generating %s key", alg); 3350*b077aed3SPierre Pronchery if (bits > 0) 3351*b077aed3SPierre Pronchery BIO_printf(bio_err, " with %d bits\n", bits); 3352*b077aed3SPierre Pronchery else 3353*b077aed3SPierre Pronchery BIO_printf(bio_err, "\n"); 3354*b077aed3SPierre Pronchery } 3355*b077aed3SPierre Pronchery if (!RAND_status()) 3356*b077aed3SPierre Pronchery BIO_printf(bio_err, "Warning: generating random key material may take a long time\n" 3357*b077aed3SPierre Pronchery "if the system has a poor entropy source\n"); 3358*b077aed3SPierre Pronchery if (EVP_PKEY_keygen(ctx, &res) <= 0) 3359*b077aed3SPierre Pronchery app_bail_out("%s: Error generating %s key\n", opt_getprog(), 3360*b077aed3SPierre Pronchery alg != NULL ? alg : "asymmetric"); 3361*b077aed3SPierre Pronchery return res; 3362*b077aed3SPierre Pronchery } 3363*b077aed3SPierre Pronchery 3364*b077aed3SPierre Pronchery EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg) 3365*b077aed3SPierre Pronchery { 3366*b077aed3SPierre Pronchery EVP_PKEY *res = NULL; 3367*b077aed3SPierre Pronchery 3368*b077aed3SPierre Pronchery if (!RAND_status()) 3369*b077aed3SPierre Pronchery BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n" 3370*b077aed3SPierre Pronchery "if the system has a poor entropy source\n"); 3371*b077aed3SPierre Pronchery if (EVP_PKEY_paramgen(ctx, &res) <= 0) 3372*b077aed3SPierre Pronchery app_bail_out("%s: Generating %s key parameters failed\n", 3373*b077aed3SPierre Pronchery opt_getprog(), alg != NULL ? alg : "asymmetric"); 3374*b077aed3SPierre Pronchery return res; 3375*b077aed3SPierre Pronchery } 3376*b077aed3SPierre Pronchery 3377*b077aed3SPierre Pronchery /* 3378*b077aed3SPierre Pronchery * Return non-zero if the legacy path is still an option. 3379*b077aed3SPierre Pronchery * This decision is based on the global command line operations and the 3380*b077aed3SPierre Pronchery * behaviour thus far. 3381*b077aed3SPierre Pronchery */ 3382*b077aed3SPierre Pronchery int opt_legacy_okay(void) 3383*b077aed3SPierre Pronchery { 3384*b077aed3SPierre Pronchery int provider_options = opt_provider_option_given(); 3385*b077aed3SPierre Pronchery int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL; 3386*b077aed3SPierre Pronchery /* 3387*b077aed3SPierre Pronchery * Having a provider option specified or a custom library context or 3388*b077aed3SPierre Pronchery * property query, is a sure sign we're not using legacy. 3389*b077aed3SPierre Pronchery */ 3390*b077aed3SPierre Pronchery if (provider_options || libctx) 3391*b077aed3SPierre Pronchery return 0; 3392*b077aed3SPierre Pronchery return 1; 3393*b077aed3SPierre Pronchery } 3394