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