/* * Read a file that contains our certificate in "PEM" format, possibly * followed by a sequence of CA certificates that should be sent to the peer * in the Certificate message. */ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) { BIO *in; int ret = 0; X509 *x = NULL; pem_password_cb *passwd_callback; void *passwd_callback_userdata; ERR_clear_error(); /* clear error stack for * SSL_CTX_use_certificate() */ if (ctx != NULL) { passwd_callback = ctx->default_passwd_callback; passwd_callback_userdata = ctx->default_passwd_callback_userdata; } else { passwd_callback = ssl->default_passwd_callback; passwd_callback_userdata = ssl->default_passwd_callback_userdata; } in = BIO_new(BIO_s_file()); if (in == NULL) { SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); goto end; } if (BIO_read_filename(in, file) <= 0) { SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); goto end; } x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback, passwd_callback_userdata); if (x == NULL) { SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } if (ctx) ret = SSL_CTX_use_certificate(ctx, x); else ret = SSL_use_certificate(ssl, x); if (ERR_peek_error() != 0) ret = 0; /* Key/certificate mismatch doesn't imply * ret==0 ... */ if (ret) { /* * If we could set up our certificate, now proceed to the CA * certificates. */ X509 *ca; int r; unsigned long err; if (ctx) r = SSL_CTX_clear_chain_certs(ctx); else r = SSL_clear_chain_certs(ssl); if (r == 0) { ret = 0; goto end; } while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback, passwd_callback_userdata)) != NULL) { if (ctx) r = SSL_CTX_add0_chain_cert(ctx, ca); else r = SSL_add0_chain_cert(ssl, ca); /* * Note that we must not free ca if it was successfully added to * the chain (while we must free the main certificate, since its * reference count is increased by SSL_CTX_use_certificate). */ if (!r) { X509_free(ca); ret = 0; goto end; } } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) ERR_clear_error(); else ret = 0; /* some real error */ } end: X509_free(x); BIO_free(in); return (ret); }
static int ngx_http_multiple_ssl_set_der_certificate(ngx_ssl_conn_t *ssl_conn, ngx_str_t *cert, ngx_str_t *key) { BIO *bio = NULL; X509 *x509 = NULL; u_long n; bio = BIO_new_file((char *) cert->data, "r"); if (bio == NULL) { return NGX_ERROR; } x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); if (x509 == NULL) { BIO_free(bio); return NGX_ERROR; } SSL_certs_clear(ssl_conn); if (SSL_use_certificate(ssl_conn, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } #if 0 if (SSL_set_ex_data(ssl_conn, ngx_ssl_certificate_index, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } #endif X509_free(x509); x509 = NULL; /* read rest of the chain */ for ( ;; ) { x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (x509 == NULL) { n = ERR_peek_last_error(); if (ERR_GET_LIB(n) == ERR_LIB_PEM && ERR_GET_REASON(n) == PEM_R_NO_START_LINE) { ERR_clear_error(); break; } BIO_free(bio); return NGX_ERROR; } if (SSL_add0_chain_cert(ssl_conn, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } } BIO_free(bio); bio = NULL; if (SSL_use_PrivateKey_file(ssl_conn, (char *) key->data, SSL_FILETYPE_PEM) != 1) { return NGX_ERROR; } return NGX_OK; }