static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret) { int ok = 0; switch (cmd) { case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { ok = (X509_load_cert_crl_file(ctx, X509_get_default_cert_file(), X509_FILETYPE_PEM) != 0); if (!ok) { X509error(X509_R_LOADING_DEFAULTS); } } else { if (argl == X509_FILETYPE_PEM) ok = (X509_load_cert_crl_file(ctx, argp, X509_FILETYPE_PEM) != 0); else ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); } break; } return (ok); }
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret) { int ok = 0; const char *file; switch (cmd) { case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { file = ossl_safe_getenv(X509_get_default_cert_file_env()); if (file) ok = (X509_load_cert_crl_file(ctx, file, X509_FILETYPE_PEM) != 0); else ok = (X509_load_cert_crl_file (ctx, X509_get_default_cert_file(), X509_FILETYPE_PEM) != 0); if (!ok) { X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS); } } else { if (argl == X509_FILETYPE_PEM) ok = (X509_load_cert_crl_file(ctx, argp, X509_FILETYPE_PEM) != 0); else ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0); } break; } return ok; }
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) { STACK_OF(X509_INFO) *inf; X509_INFO *itmp; BIO *in; int i, count = 0; if (type != X509_FILETYPE_PEM) return X509_load_cert_file(ctx, file, type); in = BIO_new_file(file, "r"); if (!in) { X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB); return 0; } inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); BIO_free(in); if (!inf) { X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB); return 0; } for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { X509_STORE_add_cert(ctx->store_ctx, itmp->x509); count++; } if (itmp->crl) { X509_STORE_add_crl(ctx->store_ctx, itmp->crl); count++; } } sk_X509_INFO_pop_free(inf, X509_INFO_free); return count; }
static int test_509_dup_cert(int n) { int ret = 0; X509_STORE_CTX *sctx = NULL; X509_STORE *store = NULL; X509_LOOKUP *lookup = NULL; const char *cert_f = test_get_argument(n); if (TEST_ptr(store = X509_STORE_new()) && TEST_ptr(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) && TEST_true(X509_load_cert_file(lookup, cert_f, X509_FILETYPE_PEM)) && TEST_true(X509_load_cert_file(lookup, cert_f, X509_FILETYPE_PEM))) ret = 1; X509_STORE_CTX_free(sctx); X509_STORE_free(store); return ret; }
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret) { int ok=0; char *file; switch (cmd) { case X509_L_FILE_LOAD: if (argl == X509_FILETYPE_DEFAULT) { file = (char *)getenv(X509_get_default_cert_file_env()); if (file) ok = (X509_load_cert_crl_file(ctx,file, X509_FILETYPE_PEM) != 0); else ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(), X509_FILETYPE_PEM) != 0); if (!ok) { OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS); } } else { if(argl == X509_FILETYPE_PEM) ok = (X509_load_cert_crl_file(ctx,argp, X509_FILETYPE_PEM) != 0); else ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0); } break; } return(ok); }
/* This function makes sure the certificate is still valid by not having any * compromised certificates in the chain. * If there is no Certificate Revocation List (CRL) it may be that the private * keys have not been compromised or the CRL has not been generated by the * Certificate Authority (CA) * * returns: 0 if certificate is valid, X509 store error code otherwise */ static int validate_certificate(void) { X509_LOOKUP *lookup = NULL; X509_STORE_CTX *verify_ctx = NULL; /* TODO: CRL and Chains are not required for the current setup, but we may * implement them in the future if (!crl) { printf("No certificate revocation list provided\n"); } if (!chain) { printf("No certificate chain provided\n"); } */ /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new())) { fprintf(stderr, "Failed X509_STORE_new() for %s\n", CERTNAME); goto error; } X509_STORE_set_verify_cb_func(store, verify_callback); /* Add the certificates to be verified to the store */ if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { fprintf(stderr, "Failed X509_STORE_add_lookup() for %s\n", CERTNAME); goto error; } /* Load the our Root cert, which can be in either DER or PEM format */ if (!X509_load_cert_file(lookup, CERTNAME, X509_FILETYPE_PEM)) { fprintf(stderr, "Failed X509_load_cert_file() for %s\n", CERTNAME); goto error; } if (crl) { if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) || (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) { fprintf(stderr, "Failed X509 crl init for %s\n", CERTNAME); goto error; } /* set the flags of the store so that CLRs are consulted */ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* create a verification context and initialize it */ if (!(verify_ctx = X509_STORE_CTX_new())) { fprintf(stderr, "Failed X509_STORE_CTX_new() for %s\n", CERTNAME); goto error; } if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) { fprintf(stderr, "Failed X509_STORE_CTX_init() for %s\n", CERTNAME); goto error; } /* Specify which cert to validate in the verify context. * This is required because we may add multiple certs to the X509 store, * but we want to validate a specific one out of the group/chain. */ X509_STORE_CTX_set_cert(verify_ctx, cert); /* verify the certificate */ if (X509_verify_cert(verify_ctx) != 1) { fprintf(stderr, "Failed X509_verify_cert() for %s\n", CERTNAME); goto error; } X509_STORE_CTX_free(verify_ctx); /* Certificate verified correctly */ return 0; error: ERR_print_errors_fp(stderr); if (verify_ctx) { X509_STORE_CTX_free(verify_ctx); } return verify_ctx->error; }
/* This function makes sure the certificate is still valid by not having any * compromised certificates in the chain. * If there is no Certificate Revocation List (CRL) it may be that the private * keys have not been compromised or the CRL has not been generated by the * Certificate Authority (CA) * * returns: 0 if certificate is valid, X509 store error code otherwise */ static int validate_certificate(X509 *cert, const char *certificate_path, const char *crl) { X509_LOOKUP *lookup = NULL; X509_STORE_CTX *verify_ctx = NULL; //TODO: Implement a chain verification when required /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new())) { error("Failed X509_STORE_new() for %s\n", certificate_path); goto error; } X509_STORE_set_verify_cb_func(store, verify_callback); if (X509_STORE_set_purpose(store, X509_PURPOSE_ANY) != 1) { error("Failed X509_STORE_set_purpose() for %s\n", certificate_path); goto error; } /* Add the certificates to be verified to the store */ if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { error("Failed X509_STORE_add_lookup() for %s\n", certificate_path); goto error; } /* Load the our Root cert, which can be in either DER or PEM format */ if (!X509_load_cert_file(lookup, certificate_path, X509_FILETYPE_PEM)) { error("Failed X509_load_cert_file() for %s\n", certificate_path); goto error; } if (crl) { if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) || (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) { error("Failed X509 crl init for %s\n", certificate_path); goto error; } /* set the flags of the store so that CLRs are consulted */ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* create a verification context and initialize it */ if (!(verify_ctx = X509_STORE_CTX_new())) { error("Failed X509_STORE_CTX_new() for %s\n", certificate_path); goto error; } if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) { error("Failed X509_STORE_CTX_init() for %s\n", certificate_path); goto error; } /* Specify which cert to validate in the verify context. * This is required because we may add multiple certs to the X509 store, * but we want to validate a specific one out of the group/chain. */ X509_STORE_CTX_set_cert(verify_ctx, cert); /* verify the certificate */ if (X509_verify_cert(verify_ctx) != 1) { error("Failed X509_verify_cert() for %s\n", certificate_path); goto error; } X509_STORE_CTX_free(verify_ctx); if (validate_authority(cert) < 0) { error("Failed to validate certificate using 'Authority Information Access'\n"); return -1; } /* Certificate verified correctly */ return 0; error: ERR_print_errors_fp(stderr); if (verify_ctx) { X509_STORE_CTX_free(verify_ctx); } return X509_STORE_CTX_get_error(verify_ctx); }
int ca_reload(struct iked *env) { struct ca_store *store = env->sc_priv; uint8_t md[EVP_MAX_MD_SIZE]; char file[PATH_MAX]; struct iovec iov[2]; struct dirent *entry; STACK_OF(X509_OBJECT) *h; X509_OBJECT *xo; X509 *x509; DIR *dir; int i, len, iovcnt = 0; /* * Load CAs */ if ((dir = opendir(IKED_CA_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CA_DIR, entry->d_name) == -1) continue; if (!X509_load_cert_file(store->ca_calookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load ca file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } log_debug("%s: loaded ca file %s", __func__, entry->d_name); } closedir(dir); /* * Load CRLs for the CAs */ if ((dir = opendir(IKED_CRL_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CRL_DIR, entry->d_name) == -1) continue; if (!X509_load_crl_file(store->ca_calookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load crl file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } /* Only enable CRL checks if we actually loaded a CRL */ X509_STORE_set_flags(store->ca_cas, X509_V_FLAG_CRL_CHECK); log_debug("%s: loaded crl file %s", __func__, entry->d_name); } closedir(dir); /* * Save CAs signatures for the IKEv2 CERTREQ */ ibuf_release(env->sc_certreq); if ((env->sc_certreq = ibuf_new(NULL, 0)) == NULL) return (-1); h = store->ca_cas->objs; for (i = 0; i < sk_X509_OBJECT_num(h); i++) { xo = sk_X509_OBJECT_value(h, i); if (xo->type != X509_LU_X509) continue; x509 = xo->data.x509; len = sizeof(md); ca_subjectpubkey_digest(x509, md, &len); log_debug("%s: %s", __func__, x509->name); if (ibuf_add(env->sc_certreq, md, len) != 0) { ibuf_release(env->sc_certreq); return (-1); } } if (ibuf_length(env->sc_certreq)) { env->sc_certreqtype = IKEV2_CERT_X509_CERT; iov[0].iov_base = &env->sc_certreqtype; iov[0].iov_len = sizeof(env->sc_certreqtype); iovcnt++; iov[1].iov_base = ibuf_data(env->sc_certreq); iov[1].iov_len = ibuf_length(env->sc_certreq); iovcnt++; log_debug("%s: loaded %zu ca certificate%s", __func__, ibuf_length(env->sc_certreq) / SHA_DIGEST_LENGTH, ibuf_length(env->sc_certreq) == SHA_DIGEST_LENGTH ? "" : "s"); (void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ, iov, iovcnt); } /* * Load certificates */ if ((dir = opendir(IKED_CERT_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CERT_DIR, entry->d_name) == -1) continue; if (!X509_load_cert_file(store->ca_certlookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load cert file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } log_debug("%s: loaded cert file %s", __func__, entry->d_name); } closedir(dir); h = store->ca_certs->objs; for (i = 0; i < sk_X509_OBJECT_num(h); i++) { xo = sk_X509_OBJECT_value(h, i); if (xo->type != X509_LU_X509) continue; x509 = xo->data.x509; (void)ca_validate_cert(env, NULL, x509, 0); } if (!env->sc_certreqtype) env->sc_certreqtype = store->ca_pubkey.id_type; log_debug("%s: local cert type %s", __func__, print_map(env->sc_certreqtype, ikev2_cert_map)); iov[0].iov_base = &env->sc_certreqtype; iov[0].iov_len = sizeof(env->sc_certreqtype); if (iovcnt == 0) iovcnt++; (void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ, iov, iovcnt); return (0); }
static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, X509_OBJECT *ret) { BY_DIR *ctx; union { struct { X509 st_x509; X509_CINF st_x509_cinf; } x509; struct { X509_CRL st_crl; X509_CRL_INFO st_crl_info; } crl; } data; int ok=0; int i,j,k; unsigned long h; BUF_MEM *b=NULL; struct stat st; X509_OBJECT stmp,*tmp; const char *postfix=""; if (name == NULL) return(0); stmp.type=type; if (type == X509_LU_X509) { data.x509.st_x509.cert_info= &data.x509.st_x509_cinf; data.x509.st_x509_cinf.subject=name; stmp.data.x509= &data.x509.st_x509; postfix=""; } else if (type == X509_LU_CRL) { data.crl.st_crl.crl= &data.crl.st_crl_info; data.crl.st_crl_info.issuer=name; stmp.data.crl= &data.crl.st_crl; postfix="r"; } else { X509err(X509_F_GET_CERT_BY_SUBJECT,X509_R_WRONG_LOOKUP_TYPE); goto finish; } if ((b=BUF_MEM_new()) == NULL) { X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_BUF_LIB); goto finish; } ctx=(BY_DIR *)xl->method_data; h=X509_NAME_hash(name); for (i=0; i<ctx->num_dirs; i++) { j=strlen(ctx->dirs[i])+1+8+6+1+1; if (!BUF_MEM_grow(b,j)) { X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE); goto finish; } k=0; for (;;) { char c = '/'; #ifdef OPENSSL_SYS_VMS c = ctx->dirs[i][strlen(ctx->dirs[i])-1]; if (c != ':' && c != '>' && c != ']') { /* If no separator is present, we assume the directory specifier is a logical name, and add a colon. We really should use better VMS routines for merging things like this, but this will do for now... -- Richard Levitte */ c = ':'; } else { c = '\0'; } #endif if (c == '\0') { /* This is special. When c == '\0', no directory separator should be added. */ BIO_snprintf(b->data,b->max, "%s%08lx.%s%d",ctx->dirs[i],h, postfix,k); } else { BIO_snprintf(b->data,b->max, "%s%c%08lx.%s%d",ctx->dirs[i],c,h, postfix,k); } k++; if (stat(b->data,&st) < 0) break; /* found one. */ if (type == X509_LU_X509) { if ((X509_load_cert_file(xl,b->data, ctx->dirs_type[i])) == 0) break; } else if (type == X509_LU_CRL) { if ((X509_load_crl_file(xl,b->data, ctx->dirs_type[i])) == 0) break; } /* else case will caught higher up */ } /* we have added it to the cache so now pull * it out again */ CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp); if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j); else tmp = NULL; CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); if (tmp != NULL) { ok=1; ret->type=tmp->type; memcpy(&ret->data,&tmp->data,sizeof(ret->data)); /* If we were going to up the reference count, * we would need to do it on a perl 'type' * basis */ /* CRYPTO_add(&tmp->data.x509->references,1, CRYPTO_LOCK_X509);*/ goto finish; } } finish: if (b != NULL) BUF_MEM_free(b); return(ok); }