comparison src/event/ngx_event_openssl.c @ 4875:386a06a22c40

OCSP stapling: loading OCSP responses. This includes the ssl_stapling_responder directive (defaults to OCSP responder set in certificate's AIA extension). OCSP response for a given certificate is requested once we get at least one connection with certificate_status extension in ClientHello, and certificate status won't be sent in the connection in question. This due to limitations in the OpenSSL API (certificate status callback is blocking). Note: SSL_CTX_use_certificate_chain_file() was reimplemented as it doesn't allow to access the certificate loaded via SSL_CTX.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 01 Oct 2012 12:47:55 +0000
parents 7c3cca603438
children f2e450929c1f
comparison
equal deleted inserted replaced
4874:d1a20423c425 4875:386a06a22c40
80 80
81 81
82 int ngx_ssl_connection_index; 82 int ngx_ssl_connection_index;
83 int ngx_ssl_server_conf_index; 83 int ngx_ssl_server_conf_index;
84 int ngx_ssl_session_cache_index; 84 int ngx_ssl_session_cache_index;
85 int ngx_ssl_certificate_index;
86 int ngx_ssl_stapling_index;
85 87
86 88
87 ngx_int_t 89 ngx_int_t
88 ngx_ssl_init(ngx_log_t *log) 90 ngx_ssl_init(ngx_log_t *log)
89 { 91 {
135 ngx_ssl_error(NGX_LOG_ALERT, log, 0, 137 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
136 "SSL_CTX_get_ex_new_index() failed"); 138 "SSL_CTX_get_ex_new_index() failed");
137 return NGX_ERROR; 139 return NGX_ERROR;
138 } 140 }
139 141
142 ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
143 NULL);
144 if (ngx_ssl_certificate_index == -1) {
145 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
146 "SSL_CTX_get_ex_new_index() failed");
147 return NGX_ERROR;
148 }
149
150 ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
151 NULL);
152 if (ngx_ssl_stapling_index == -1) {
153 ngx_ssl_error(NGX_LOG_ALERT, log, 0,
154 "SSL_CTX_get_ex_new_index() failed");
155 return NGX_ERROR;
156 }
157
140 return NGX_OK; 158 return NGX_OK;
141 } 159 }
142 160
143 161
144 ngx_int_t 162 ngx_int_t
216 234
217 ngx_int_t 235 ngx_int_t
218 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, 236 ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
219 ngx_str_t *key) 237 ngx_str_t *key)
220 { 238 {
239 BIO *bio;
240 X509 *x509;
241 u_long n;
242
221 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) { 243 if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
222 return NGX_ERROR; 244 return NGX_ERROR;
223 } 245 }
224 246
225 if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert->data) 247 /*
248 * we can't use SSL_CTX_use_certificate_chain_file() as it doesn't
249 * allow to access certificate later from SSL_CTX, so we reimplement
250 * it here
251 */
252
253 bio = BIO_new_file((char *) cert->data, "r");
254 if (bio == NULL) {
255 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
256 "BIO_new_file(\"%s\") failed", cert->data);
257 return NGX_ERROR;
258 }
259
260 x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
261 if (x509 == NULL) {
262 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
263 "PEM_read_bio_X509_AUX(\"%s\") failed", cert->data);
264 BIO_free(bio);
265 return NGX_ERROR;
266 }
267
268 if (SSL_CTX_use_certificate(ssl->ctx, x509) == 0) {
269 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
270 "SSL_CTX_use_certificate(\"%s\") failed", cert->data);
271 X509_free(x509);
272 BIO_free(bio);
273 return NGX_ERROR;
274 }
275
276 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
226 == 0) 277 == 0)
227 { 278 {
228 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 279 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
229 "SSL_CTX_use_certificate_chain_file(\"%s\") failed", 280 "SSL_CTX_set_ex_data() failed");
230 cert->data); 281 return NGX_ERROR;
231 return NGX_ERROR; 282 }
232 } 283
284 X509_free(x509);
285
286 /* read rest of the chain */
287
288 for ( ;; ) {
289
290 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
291 if (x509 == NULL) {
292 n = ERR_peek_last_error();
293
294 if (ERR_GET_LIB(n) == ERR_LIB_PEM
295 && ERR_GET_REASON(n) == PEM_R_NO_START_LINE)
296 {
297 /* end of file */
298 ERR_clear_error();
299 break;
300 }
301
302 /* some real error */
303
304 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
305 "PEM_read_bio_X509(\"%s\") failed", cert->data);
306 BIO_free(bio);
307 return NGX_ERROR;
308 }
309
310 if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
311 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
312 "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
313 cert->data);
314 X509_free(x509);
315 BIO_free(bio);
316 return NGX_ERROR;
317 }
318 }
319
320 BIO_free(bio);
233 321
234 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { 322 if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) {
235 return NGX_ERROR; 323 return NGX_ERROR;
236 } 324 }
237 325