xref: /unit/src/nxt_openssl.c (revision 0:a63ceefd6ab0)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 #include <openssl/ssl.h>
9 #include <openssl/conf.h>
10 #include <openssl/err.h>
11 
12 
13 typedef struct {
14     SSL            *session;
15 
16     int            ssl_error;
17     uint8_t        times;      /* 2 bits */
18 
19     nxt_buf_mem_t  buffer;
20 } nxt_openssl_conn_t;
21 
22 
23 static nxt_int_t nxt_openssl_server_init(nxt_ssltls_conf_t *conf);
24 
25 static void nxt_openssl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf,
26     nxt_event_conn_t *c);
27 static void nxt_openssl_session_cleanup(void *data);
28 static void nxt_openssl_conn_handshake(nxt_thread_t *thr, void *obj,
29     void *data);
30 static void nxt_openssl_conn_io_read(nxt_thread_t *thr, void *obj, void *data);
31 static void nxt_openssl_conn_io_shutdown(nxt_thread_t *thr, void *obj,
32     void *data);
33 static ssize_t nxt_openssl_conn_io_write_chunk(nxt_thread_t *thr,
34     nxt_event_conn_t *c, nxt_buf_t *b, size_t limit);
35 static ssize_t nxt_openssl_conn_io_send(nxt_event_conn_t *c, void *buf,
36     size_t size);
37 static nxt_int_t nxt_openssl_conn_test_error(nxt_thread_t *thr,
38     nxt_event_conn_t *c, int ret, nxt_err_t sys_err,
39     nxt_work_handler_t handler);
40 static void nxt_cdecl nxt_openssl_conn_error(nxt_event_conn_t *c, nxt_err_t err,
41     const char *fmt, ...);
42 static nxt_uint_t nxt_openssl_log_error_level(nxt_event_conn_t *c,
43     nxt_err_t err);
44 static void nxt_cdecl nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log,
45     const char *fmt, ...);
46 static u_char *nxt_openssl_copy_error(u_char *p, u_char *end);
47 
48 
49 const nxt_ssltls_lib_t  nxt_openssl_lib = {
50     nxt_openssl_server_init,
51     NULL,
52 };
53 
54 
55 static nxt_event_conn_io_t  nxt_openssl_event_conn_io = {
56     NULL,
57     NULL,
58 
59     nxt_openssl_conn_io_read,
60     NULL,
61     NULL,
62 
63     nxt_event_conn_io_write,
64     nxt_openssl_conn_io_write_chunk,
65     NULL,
66     NULL,
67     nxt_openssl_conn_io_send,
68 
69     nxt_openssl_conn_io_shutdown,
70 };
71 
72 
73 static long  nxt_openssl_version;
74 static int   nxt_openssl_connection_index;
75 
76 
77 static nxt_int_t
78 nxt_openssl_start(nxt_thread_t *thr)
79 {
80     int  index;
81 
82     if (nxt_fast_path(nxt_openssl_version != 0)) {
83         return NXT_OK;
84     }
85 
86     SSL_load_error_strings();
87 
88     OPENSSL_config(NULL);
89 
90     /*
91      * SSL_library_init(3):
92      *
93      *   SSL_library_init() always returns "1",
94      *   so it is safe to discard the return value.
95      */
96     (void) SSL_library_init();
97 
98     nxt_openssl_version = SSLeay();
99 
100     nxt_log_error(NXT_LOG_INFO, thr->log, "%s, %xl",
101                   SSLeay_version(SSLEAY_VERSION), nxt_openssl_version);
102 
103 #ifndef SSL_OP_NO_COMPRESSION
104     {
105         /*
106          * Disable gzip compression in OpenSSL prior to 1.0.0
107          * version, this saves about 522K per connection.
108          */
109         int                 n;
110         STACK_OF(SSL_COMP)  *ssl_comp_methods;
111 
112         ssl_comp_methods = SSL_COMP_get_compression_methods();
113 
114         for (n = sk_SSL_COMP_num(ssl_comp_methods); n != 0; n--) {
115             (void) sk_SSL_COMP_pop(ssl_comp_methods);
116         }
117     }
118 #endif
119 
120     index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
121 
122     if (index == -1) {
123         nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
124                               "SSL_get_ex_new_index() failed");
125         return NXT_ERROR;
126     }
127 
128     nxt_openssl_connection_index = index;
129 
130     return NXT_OK;
131 }
132 
133 
134 static nxt_int_t
135 nxt_openssl_server_init(nxt_ssltls_conf_t *conf)
136 {
137     SSL_CTX              *ctx;
138     const char           *certificate, *key, *ciphers, *ca_certificate;
139     nxt_thread_t         *thr;
140     STACK_OF(X509_NAME)  *list;
141 
142     thr = nxt_thread();
143 
144     if (nxt_openssl_start(thr) != NXT_OK) {
145         return NXT_ERROR;
146     }
147 
148     ctx = SSL_CTX_new(SSLv23_server_method());
149     if (ctx == NULL) {
150         nxt_openssl_log_error(NXT_LOG_CRIT, thr->log, "SSL_CTX_new() failed");
151         return NXT_ERROR;
152     }
153 
154     conf->ctx = ctx;
155     conf->conn_init = nxt_openssl_conn_init;
156 
157 #ifdef SSL_OP_NO_COMPRESSION
158     /*
159      * Disable gzip compression in OpenSSL 1.0.0,
160      * this saves about 522K per connection.
161      */
162     SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
163 #endif
164 
165 #ifdef SSL_MODE_RELEASE_BUFFERS
166 
167     if (nxt_openssl_version >= 10001078) {
168         /*
169          * Allow to release read and write buffers in OpenSSL 1.0.0,
170          * this saves about 34K per idle connection.  It is not safe
171          * before OpenSSL 1.0.1h (CVE-2010-5298).
172          */
173         SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
174     }
175 
176 #endif
177 
178     certificate = conf->certificate;
179 
180     if (SSL_CTX_use_certificate_chain_file(ctx, certificate) == 0) {
181         nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
182                               "SSL_CTX_use_certificate_file(\"%s\") failed",
183                               certificate);
184         goto fail;
185     }
186 
187     key = conf->certificate_key;
188 
189     if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) == 0) {
190         nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
191                               "SSL_CTX_use_PrivateKey_file(\"%s\") failed",
192                               key);
193         goto fail;
194     }
195 
196     ciphers = (conf->ciphers != NULL) ? conf->ciphers : "HIGH:!aNULL:!MD5";
197 
198     if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
199         nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
200                               "SSL_CTX_set_cipher_list(\"%s\") failed",
201                               ciphers);
202         goto fail;
203     }
204 
205     SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
206 
207     if (conf->ca_certificate != NULL) {
208 
209         /* TODO: verify callback */
210         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
211 
212         /* TODO: verify depth */
213         SSL_CTX_set_verify_depth(ctx, 1);
214 
215         ca_certificate = conf->ca_certificate;
216 
217         if (SSL_CTX_load_verify_locations(ctx, ca_certificate, NULL) == 0) {
218             nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
219                               "SSL_CTX_load_verify_locations(\"%s\") failed",
220                               ca_certificate);
221             goto fail;
222         }
223 
224         list = SSL_load_client_CA_file(ca_certificate);
225 
226         if (list == NULL) {
227             nxt_openssl_log_error(NXT_LOG_CRIT, thr->log,
228                               "SSL_load_client_CA_file(\"%s\") failed",
229                               ca_certificate);
230             goto fail;
231         }
232 
233         /*
234          * SSL_load_client_CA_file() in OpenSSL prior to 0.9.7h and
235          * 0.9.8 versions always leaves an error in the error queue.
236          */
237         ERR_clear_error();
238 
239         SSL_CTX_set_client_CA_list(ctx, list);
240     }
241 
242     return NXT_OK;
243 
244 fail:
245 
246     SSL_CTX_free(ctx);
247 
248     return NXT_ERROR;
249 }
250 
251 
252 static void
253 nxt_openssl_conn_init(nxt_thread_t *thr, nxt_ssltls_conf_t *conf,
254     nxt_event_conn_t *c)
255 {
256     int                     ret;
257     SSL                     *s;
258     SSL_CTX                 *ctx;
259     nxt_openssl_conn_t      *ssltls;
260     nxt_mem_pool_cleanup_t  *mpcl;
261 
262     nxt_log_debug(c->socket.log, "openssl conn init");
263 
264     ssltls = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_openssl_conn_t));
265     if (ssltls == NULL) {
266         goto fail;
267     }
268 
269     c->u.ssltls = ssltls;
270     nxt_buf_mem_set_size(&ssltls->buffer, conf->buffer_size);
271 
272     mpcl = nxt_mem_pool_cleanup(c->mem_pool, 0);
273     if (mpcl == NULL) {
274         goto fail;
275     }
276 
277     ctx = conf->ctx;
278 
279     s = SSL_new(ctx);
280     if (s == NULL) {
281         nxt_openssl_log_error(NXT_LOG_CRIT, c->socket.log, "SSL_new() failed");
282         goto fail;
283     }
284 
285     ssltls->session = s;
286     mpcl->handler = nxt_openssl_session_cleanup;
287     mpcl->data = ssltls;
288 
289     ret = SSL_set_fd(s, c->socket.fd);
290 
291     if (ret == 0) {
292         nxt_openssl_log_error(NXT_LOG_CRIT, c->socket.log,
293                               "SSL_set_fd(%d) failed", c->socket.fd);
294         goto fail;
295     }
296 
297     SSL_set_accept_state(s);
298 
299     if (SSL_set_ex_data(s, nxt_openssl_connection_index, c) == 0) {
300         nxt_openssl_log_error(NXT_LOG_CRIT, c->socket.log,
301                               "SSL_set_ex_data() failed");
302         goto fail;
303     }
304 
305     c->io = &nxt_openssl_event_conn_io;
306     c->sendfile = NXT_CONN_SENDFILE_OFF;
307 
308     nxt_openssl_conn_handshake(thr, c, c->socket.data);
309     return;
310 
311 fail:
312 
313     nxt_event_conn_io_handle(thr, c->read_work_queue,
314                              c->read_state->error_handler, c, c->socket.data);
315 }
316 
317 
318 static void
319 nxt_openssl_session_cleanup(void *data)
320 {
321     nxt_openssl_conn_t  *ssltls;
322 
323     ssltls = data;
324 
325     nxt_thread_log_debug("openssl session cleanup");
326 
327     nxt_free(ssltls->buffer.start);
328 
329     SSL_free(ssltls->session);
330 }
331 
332 
333 static void
334 nxt_openssl_conn_handshake(nxt_thread_t *thr, void *obj, void *data)
335 {
336     int                 ret;
337     nxt_int_t           n;
338     nxt_err_t           err;
339     nxt_event_conn_t    *c;
340     nxt_openssl_conn_t  *ssltls;
341 
342     c = obj;
343     ssltls = c->u.ssltls;
344 
345     nxt_log_debug(thr->log, "openssl conn handshake: %d", ssltls->times);
346 
347     /* "ssltls->times == 1" is suitable to run SSL_do_handshake() in job. */
348 
349     ret = SSL_do_handshake(ssltls->session);
350 
351     err = (ret <= 0) ? nxt_socket_errno : 0;
352 
353     nxt_thread_time_debug_update(thr);
354 
355     nxt_log_debug(thr->log, "SSL_do_handshake(%d): %d err:%d",
356                   c->socket.fd, ret, err);
357 
358     if (ret > 0) {
359         /* ret == 1, the handshake was successfully completed. */
360         nxt_openssl_conn_io_read(thr, c, data);
361         return;
362     }
363 
364     n = nxt_openssl_conn_test_error(thr, c, ret, err,
365                                     nxt_openssl_conn_handshake);
366 
367     if (n == NXT_ERROR) {
368         nxt_openssl_conn_error(c, err, "SSL_do_handshake(%d) failed",
369                                c->socket.fd);
370 
371         nxt_event_conn_io_handle(thr, c->read_work_queue,
372                                  c->read_state->error_handler, c, data);
373 
374     } else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) {
375         ssltls->times++;
376     }
377 }
378 
379 
380 static void
381 nxt_openssl_conn_io_read(nxt_thread_t *thr, void *obj, void *data)
382 {
383     int                 ret;
384     nxt_buf_t           *b;
385     nxt_int_t           n;
386     nxt_err_t           err;
387     nxt_event_conn_t    *c;
388     nxt_work_handler_t  handler;
389     nxt_openssl_conn_t  *ssltls;
390 
391     c = obj;
392 
393     nxt_log_debug(thr->log, "openssl conn read");
394 
395     handler = c->read_state->ready_handler;
396     b = c->read;
397 
398     /* b == NULL is used to test descriptor readiness. */
399 
400     if (b != NULL) {
401         ssltls = c->u.ssltls;
402 
403         ret = SSL_read(ssltls->session, b->mem.free, b->mem.end - b->mem.free);
404 
405         err = (ret <= 0) ? nxt_socket_errno : 0;
406 
407         nxt_log_debug(thr->log, "SSL_read(%d, %p, %uz): %d err:%d",
408                       c->socket.fd, b->mem.free, b->mem.end - b->mem.free,
409                       ret, err);
410 
411         if (ret > 0) {
412             /* c->socket.read_ready is kept. */
413             b->mem.free += ret;
414             handler = c->read_state->ready_handler;
415 
416         } else {
417             n = nxt_openssl_conn_test_error(thr, c, ret, err,
418                                             nxt_openssl_conn_io_read);
419 
420             if (nxt_fast_path(n != NXT_ERROR)) {
421                 return;
422             }
423 
424             nxt_openssl_conn_error(c, err, "SSL_read(%d, %p, %uz) failed",
425                                    c->socket.fd, b->mem.free,
426                                    b->mem.end - b->mem.free);
427 
428             handler = c->read_state->error_handler;
429         }
430     }
431 
432     nxt_event_conn_io_handle(thr, c->read_work_queue, handler, c, data);
433 }
434 
435 
436 static ssize_t
437 nxt_openssl_conn_io_write_chunk(nxt_thread_t *thr, nxt_event_conn_t *c,
438     nxt_buf_t *b, size_t limit)
439 {
440     nxt_openssl_conn_t  *ssltls;
441 
442     nxt_log_debug(thr->log, "openssl conn write chunk");
443 
444     ssltls = c->u.ssltls;
445 
446     return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit);
447 }
448 
449 
450 static ssize_t
451 nxt_openssl_conn_io_send(nxt_event_conn_t *c, void *buf, size_t size)
452 {
453     int                 ret;
454     nxt_err_t           err;
455     nxt_int_t           n;
456     nxt_openssl_conn_t  *ssltls;
457 
458     ssltls = c->u.ssltls;
459 
460     ret = SSL_write(ssltls->session, buf, size);
461 
462     if (ret <= 0) {
463         err = nxt_socket_errno;
464         c->socket.error = err;
465 
466     } else {
467         err = 0;
468     }
469 
470     nxt_log_debug(c->socket.log, "SSL_write(%d, %p, %uz): %d err:%d",
471                   c->socket.fd, buf, size, ret, err);
472 
473     if (ret > 0) {
474         return ret;
475     }
476 
477     n = nxt_openssl_conn_test_error(nxt_thread(), c, ret, err,
478                                     nxt_event_conn_io_write);
479 
480     if (n == NXT_ERROR) {
481         nxt_openssl_conn_error(c, err, "SSL_write(%d, %p, %uz) failed",
482                                c->socket.fd, buf, size);
483     }
484 
485     return n;
486 }
487 
488 
489 static void
490 nxt_openssl_conn_io_shutdown(nxt_thread_t *thr, void *obj, void *data)
491 {
492     int                 ret, mode;
493     SSL                 *s;
494     nxt_err_t           err;
495     nxt_int_t           n;
496     nxt_bool_t          quiet, once;
497     nxt_event_conn_t    *c;
498     nxt_work_handler_t  handler;
499     nxt_openssl_conn_t  *ssltls;
500 
501     c = obj;
502 
503     nxt_log_debug(thr->log, "openssl conn shutdown");
504 
505     ssltls = c->u.ssltls;
506     s = ssltls->session;
507 
508     if (s == NULL) {
509         handler = c->write_state->close_handler;
510         goto done;
511     }
512 
513     mode = SSL_get_shutdown(s);
514 
515     if (c->socket.timedout || c->socket.error != 0) {
516         quiet = 1;
517 
518     } else if (c->socket.closed && !(mode & SSL_RECEIVED_SHUTDOWN)) {
519         quiet = 1;
520 
521     } else {
522         quiet = 0;
523     }
524 
525     SSL_set_quiet_shutdown(s, quiet);
526 
527     once = 1;
528 
529     for ( ;; ) {
530         SSL_set_shutdown(s, mode);
531 
532         ret = SSL_shutdown(s);
533 
534         err = (ret <= 0) ? nxt_socket_errno : 0;
535 
536         nxt_log_debug(thr->log, "SSL_shutdown(%d, %d, %b): %d err:%d",
537                       c->socket.fd, mode, quiet, ret, err);
538 
539         if (ret > 0) {
540             /* ret == 1, the shutdown was successfully completed. */
541             handler = c->write_state->close_handler;
542             goto done;
543         }
544 
545         if (ret == 0) {
546             /*
547              * If SSL_shutdown() returns 0 then it should be called
548              * again.  The second SSL_shutdown() call should returns
549              * -1/SSL_ERROR_WANT_READ or -1/SSL_ERROR_WANT_WRITE.
550              * OpenSSL prior to 0.9.8m version however never returns
551              * -1 at all.  Fortunately, OpenSSL internals preserve
552              * correct status available via SSL_get_error(-1).
553              */
554             if (once) {
555                 mode = SSL_get_shutdown(s);
556                 once = 0;
557                 continue;
558             }
559 
560             ret = -1;
561         }
562 
563         /* ret == -1 */
564 
565         break;
566     }
567 
568     n = nxt_openssl_conn_test_error(thr, c, ret, err,
569                                     nxt_openssl_conn_io_shutdown);
570 
571     if (nxt_fast_path(n == 0)) {
572         return;
573     }
574 
575     if (n != NXT_ERROR) {  /* n == NXT_AGAIN */
576         c->socket.error_handler = c->read_state->error_handler;
577         nxt_event_timer_add(thr->engine, &c->read_timer, 5000);
578         return;
579     }
580 
581     nxt_openssl_conn_error(c, err, "SSL_shutdown(%d) failed", c->socket.fd);
582 
583     handler = c->write_state->error_handler;
584 
585 done:
586 
587     nxt_event_conn_io_handle(thr, c->write_work_queue, handler, c, data);
588 }
589 
590 
591 static nxt_int_t
592 nxt_openssl_conn_test_error(nxt_thread_t *thr, nxt_event_conn_t *c, int ret,
593     nxt_err_t sys_err, nxt_work_handler_t handler)
594 {
595     u_long              lib_err;
596     nxt_work_queue_t    *wq;
597     nxt_openssl_conn_t  *ssltls;
598 
599     ssltls = c->u.ssltls;
600 
601     ssltls->ssl_error = SSL_get_error(ssltls->session, ret);
602 
603     nxt_log_debug(c->socket.log, "SSL_get_error(): %d", ssltls->ssl_error);
604 
605     switch (ssltls->ssl_error) {
606 
607     case SSL_ERROR_WANT_READ:
608         nxt_event_fd_block_write(thr->engine, &c->socket);
609 
610         c->socket.read_ready = 0;
611         c->socket.read_handler = handler;
612 
613         if (nxt_event_fd_is_disabled(c->socket.read)) {
614             nxt_event_fd_enable_read(thr->engine, &c->socket);
615         }
616 
617         return NXT_AGAIN;
618 
619     case SSL_ERROR_WANT_WRITE:
620         nxt_event_fd_block_read(thr->engine, &c->socket);
621 
622         c->socket.write_ready = 0;
623         c->socket.write_handler = handler;
624 
625         if (nxt_event_fd_is_disabled(c->socket.write)) {
626             nxt_event_fd_enable_write(thr->engine, &c->socket);
627         }
628 
629         return NXT_AGAIN;
630 
631     case SSL_ERROR_SYSCALL:
632 
633         lib_err = ERR_peek_error();
634 
635         nxt_log_debug(c->socket.log, "ERR_peek_error(): %l", lib_err);
636 
637         if (sys_err != 0 || lib_err != 0) {
638             return NXT_ERROR;
639         }
640 
641         /* A connection was just closed. */
642         c->socket.closed = 1;
643 
644         /* Fall through. */
645 
646     case SSL_ERROR_ZERO_RETURN:
647         /* A "close notify" alert. */
648 
649         if (c->read_state != NULL) {
650             wq = c->read_work_queue;
651             handler = c->read_state->close_handler;
652 
653         } else {
654             wq = c->write_work_queue;
655             handler = c->write_state->close_handler;
656         }
657 
658         nxt_event_conn_io_handle(thr, wq, handler, c, c->socket.data);
659 
660         return 0;
661 
662     default: /* SSL_ERROR_SSL, etc. */
663         c->socket.error = 1000;  /* Nonexistent errno code. */
664         return NXT_ERROR;
665     }
666 }
667 
668 
669 static void nxt_cdecl
670 nxt_openssl_conn_error(nxt_event_conn_t *c, nxt_err_t err, const char *fmt, ...)
671 {
672     u_char      *p, *end;
673     va_list     args;
674     nxt_uint_t  level;
675     u_char      msg[NXT_MAX_ERROR_STR];
676 
677     c->socket.error = err;
678     level = nxt_openssl_log_error_level(c, err);
679 
680     if (nxt_log_level_enough(c->socket.log, level)) {
681 
682         end = msg + sizeof(msg);
683 
684         va_start(args, fmt);
685         p = nxt_vsprintf(msg, end, fmt, args);
686         va_end(args);
687 
688         if (err != 0) {
689             p = nxt_sprintf(p, end, " %E", err);
690         }
691 
692         p = nxt_openssl_copy_error(p, end);
693 
694         nxt_log_error(level, c->socket.log, "%*s", p - msg, msg);
695 
696     } else {
697         ERR_clear_error();
698     }
699 }
700 
701 
702 static nxt_uint_t
703 nxt_openssl_log_error_level(nxt_event_conn_t *c, nxt_err_t err)
704 {
705     switch (ERR_GET_REASON(ERR_peek_error())) {
706 
707     case 0:
708         return nxt_socket_error_level(err, c->socket.log_error);
709 
710     case SSL_R_BAD_CHANGE_CIPHER_SPEC:                    /*  103 */
711     case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:                 /*  129 */
712     case SSL_R_DIGEST_CHECK_FAILED:                       /*  149 */
713     case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:             /*  151 */
714     case SSL_R_EXCESSIVE_MESSAGE_SIZE:                    /*  152 */
715     case SSL_R_LENGTH_MISMATCH:                           /*  159 */
716     case SSL_R_NO_CIPHERS_PASSED:                         /*  182 */
717     case SSL_R_NO_CIPHERS_SPECIFIED:                      /*  183 */
718     case SSL_R_NO_COMPRESSION_SPECIFIED:                  /*  187 */
719     case SSL_R_NO_SHARED_CIPHER:                          /*  193 */
720     case SSL_R_RECORD_LENGTH_MISMATCH:                    /*  213 */
721 #ifdef SSL_R_PARSE_TLSEXT
722     case SSL_R_PARSE_TLSEXT:                              /*  227 */
723 #endif
724     case SSL_R_UNEXPECTED_MESSAGE:                        /*  244 */
725     case SSL_R_UNEXPECTED_RECORD:                         /*  245 */
726     case SSL_R_UNKNOWN_ALERT_TYPE:                        /*  246 */
727     case SSL_R_UNKNOWN_PROTOCOL:                          /*  252 */
728     case SSL_R_WRONG_VERSION_NUMBER:                      /*  267 */
729     case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:       /*  281 */
730 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
731     case SSL_R_RENEGOTIATE_EXT_TOO_LONG:                  /*  335 */
732     case SSL_R_RENEGOTIATION_ENCODING_ERR:                /*  336 */
733     case SSL_R_RENEGOTIATION_MISMATCH:                    /*  337 */
734 #endif
735 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
736     case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:      /*  338 */
737 #endif
738 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
739     case SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING:          /*  345 */
740 #endif
741     case 1000:/* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
742     case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:            /* 1010 */
743     case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:                /* 1020 */
744     case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:             /* 1021 */
745     case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:               /* 1022 */
746     case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:         /* 1030 */
747     case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:             /* 1040 */
748     case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:             /* 1047 */
749         break;
750 
751     case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:                /* 1041 */
752     case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:               /* 1042 */
753     case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:       /* 1043 */
754     case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:           /* 1044 */
755     case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:           /* 1045 */
756     case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:           /* 1046 */
757     case SSL_R_TLSV1_ALERT_UNKNOWN_CA:                    /* 1048 */
758     case SSL_R_TLSV1_ALERT_ACCESS_DENIED:                 /* 1049 */
759     case SSL_R_TLSV1_ALERT_DECODE_ERROR:                  /* 1050 */
760     case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:                 /* 1051 */
761     case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:            /* 1060 */
762     case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:              /* 1070 */
763     case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:         /* 1071 */
764     case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:                /* 1080 */
765     case SSL_R_TLSV1_ALERT_USER_CANCELLED:                /* 1090 */
766     case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:              /* 1100 */
767         return NXT_LOG_ERR;
768 
769     default:
770         return NXT_LOG_CRIT;
771     }
772 
773     return NXT_LOG_INFO;
774 }
775 
776 
777 static void nxt_cdecl
778 nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...)
779 {
780     u_char   *p, *end;
781     va_list  args;
782     u_char   msg[NXT_MAX_ERROR_STR];
783 
784     end = msg + sizeof(msg);
785 
786     va_start(args, fmt);
787     p = nxt_vsprintf(msg, end, fmt, args);
788     va_end(args);
789 
790     p = nxt_openssl_copy_error(p, end);
791 
792     nxt_log_error(level, log, "%*s", p - msg, msg);
793 }
794 
795 
796 static u_char *
797 nxt_openssl_copy_error(u_char *p, u_char *end)
798 {
799     int         flags;
800     u_long      err;
801     nxt_bool_t  clear;
802     const char  *data, *delimiter;
803 
804     err = ERR_peek_error();
805     if (err == 0) {
806         return p;
807     }
808 
809     /* Log the most relevant error message ... */
810     data = ERR_reason_error_string(err);
811 
812     p = nxt_sprintf(p, end, " (%d: %s) (OpenSSL: ", ERR_GET_REASON(err), data);
813 
814     /*
815      * ... followed by all queued cumbersome OpenSSL
816      * error messages and drain the error queue.
817      */
818     delimiter = "";
819     clear = 0;
820 
821     for ( ;; ) {
822         err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
823         if (err == 0) {
824             break;
825         }
826 
827         p = nxt_sprintf(p, end, "%s", delimiter);
828 
829         ERR_error_string_n(err, (char *) p, end - p);
830 
831         while (p < end && *p != '\0') {
832             p++;
833         }
834 
835         if ((flags & ERR_TXT_STRING) != 0) {
836             p = nxt_sprintf(p, end, ":%s", data);
837         }
838 
839         clear |= ((flags & ERR_TXT_MALLOCED) != 0);
840 
841         delimiter = "; ";
842     }
843 
844     /* Deallocate additional data. */
845 
846     if (clear) {
847         ERR_clear_error();
848     }
849 
850     if (p < end) {
851         *p++ = ')';
852     }
853 
854     return p;
855 }
856