xref: /unit/src/nxt_openssl.c (revision 564:762f8c976ead)
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_ALERT, 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_ALERT, 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_ALERT, 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_ALERT, 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_ALERT, 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_ALERT, 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_ALERT, 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_mp_zget(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_ALERT, c->socket.log,
277                               "SSL_new() failed");
278         goto fail;
279     }
280 
281     ssltls->session = s;
282     mpcl->handler = nxt_openssl_session_cleanup;
283     mpcl->data = ssltls;
284 
285     ret = SSL_set_fd(s, c->socket.fd);
286 
287     if (ret == 0) {
288         nxt_openssl_log_error(NXT_LOG_ALERT, c->socket.log,
289                               "SSL_set_fd(%d) failed", c->socket.fd);
290         goto fail;
291     }
292 
293     SSL_set_accept_state(s);
294 
295     if (SSL_set_ex_data(s, nxt_openssl_connection_index, c) == 0) {
296         nxt_openssl_log_error(NXT_LOG_ALERT, c->socket.log,
297                               "SSL_set_ex_data() failed");
298         goto fail;
299     }
300 
301     c->io = &nxt_openssl_conn_io;
302     c->sendfile = NXT_CONN_SENDFILE_OFF;
303 
304     nxt_openssl_conn_handshake(task, c, c->socket.data);
305     return;
306 
307 fail:
308 
309     nxt_work_queue_add(c->read_work_queue, c->read_state->error_handler,
310                        task, c, c->socket.data);
311 }
312 
313 
314 static void
315 nxt_openssl_session_cleanup(nxt_task_t *task, void *data)
316 {
317     nxt_openssl_conn_t  *ssltls;
318 
319     ssltls = data;
320 
321     nxt_debug(task, "openssl session cleanup");
322 
323     nxt_free(ssltls->buffer.start);
324 
325     SSL_free(ssltls->session);
326 }
327 
328 
329 static void
330 nxt_openssl_conn_handshake(nxt_task_t *task, void *obj, void *data)
331 {
332     int                 ret;
333     nxt_int_t           n;
334     nxt_err_t           err;
335     nxt_conn_t          *c;
336     nxt_openssl_conn_t  *ssltls;
337 
338     c = obj;
339     ssltls = c->u.ssltls;
340 
341     nxt_debug(task, "openssl conn handshake: %d", ssltls->times);
342 
343     /* "ssltls->times == 1" is suitable to run SSL_do_handshake() in job. */
344 
345     ret = SSL_do_handshake(ssltls->session);
346 
347     err = (ret <= 0) ? nxt_socket_errno : 0;
348 
349     nxt_thread_time_debug_update(task->thread);
350 
351     nxt_debug(task, "SSL_do_handshake(%d): %d err:%d", c->socket.fd, ret, err);
352 
353     if (ret > 0) {
354         /* ret == 1, the handshake was successfully completed. */
355         nxt_openssl_conn_io_read(task, c, data);
356         return;
357     }
358 
359     n = nxt_openssl_conn_test_error(task, c, ret, err,
360                                     nxt_openssl_conn_handshake);
361 
362     if (n == NXT_ERROR) {
363         nxt_openssl_conn_error(c, err, "SSL_do_handshake(%d) failed",
364                                c->socket.fd);
365 
366         nxt_work_queue_add(c->read_work_queue, c->read_state->error_handler,
367                            task, c, data);
368 
369     } else if (ssltls->ssl_error == SSL_ERROR_WANT_READ && ssltls->times < 2) {
370         ssltls->times++;
371     }
372 }
373 
374 
375 static void
376 nxt_openssl_conn_io_read(nxt_task_t *task, void *obj, void *data)
377 {
378     int                 ret;
379     nxt_buf_t           *b;
380     nxt_int_t           n;
381     nxt_err_t           err;
382     nxt_conn_t          *c;
383     nxt_work_handler_t  handler;
384     nxt_openssl_conn_t  *ssltls;
385 
386     c = obj;
387 
388     nxt_debug(task, "openssl conn read");
389 
390     handler = c->read_state->ready_handler;
391     b = c->read;
392 
393     /* b == NULL is used to test descriptor readiness. */
394 
395     if (b != NULL) {
396         ssltls = c->u.ssltls;
397 
398         ret = SSL_read(ssltls->session, b->mem.free, b->mem.end - b->mem.free);
399 
400         err = (ret <= 0) ? nxt_socket_errno : 0;
401 
402         nxt_debug(task, "SSL_read(%d, %p, %uz): %d err:%d",
403                   c->socket.fd, b->mem.free, b->mem.end - b->mem.free,
404                   ret, err);
405 
406         if (ret > 0) {
407             /* c->socket.read_ready is kept. */
408             b->mem.free += ret;
409             handler = c->read_state->ready_handler;
410 
411         } else {
412             n = nxt_openssl_conn_test_error(task, c, ret, err,
413                                             nxt_openssl_conn_io_read);
414 
415             if (nxt_fast_path(n != NXT_ERROR)) {
416                 return;
417             }
418 
419             nxt_openssl_conn_error(c, err, "SSL_read(%d, %p, %uz) failed",
420                                    c->socket.fd, b->mem.free,
421                                    b->mem.end - b->mem.free);
422 
423             handler = c->read_state->error_handler;
424         }
425     }
426 
427     nxt_work_queue_add(c->read_work_queue, handler, task, c, data);
428 }
429 
430 
431 static ssize_t
432 nxt_openssl_conn_io_write_chunk(nxt_conn_t *c, nxt_buf_t *b, size_t limit)
433 {
434     nxt_openssl_conn_t  *ssltls;
435 
436     nxt_debug(c->socket.task, "openssl conn write chunk");
437 
438     ssltls = c->u.ssltls;
439 
440     return nxt_sendbuf_copy_coalesce(c, &ssltls->buffer, b, limit);
441 }
442 
443 
444 static ssize_t
445 nxt_openssl_conn_io_send(nxt_conn_t *c, void *buf, size_t size)
446 {
447     int                 ret;
448     nxt_err_t           err;
449     nxt_int_t           n;
450     nxt_openssl_conn_t  *ssltls;
451 
452     ssltls = c->u.ssltls;
453 
454     ret = SSL_write(ssltls->session, buf, size);
455 
456     if (ret <= 0) {
457         err = nxt_socket_errno;
458         c->socket.error = err;
459 
460     } else {
461         err = 0;
462     }
463 
464     nxt_log_debug(c->socket.log, "SSL_write(%d, %p, %uz): %d err:%d",
465                   c->socket.fd, buf, size, ret, err);
466 
467     if (ret > 0) {
468         return ret;
469     }
470 
471     n = nxt_openssl_conn_test_error(c->socket.task, c, ret, err,
472                                     nxt_conn_io_write);
473 
474     if (n == NXT_ERROR) {
475         nxt_openssl_conn_error(c, err, "SSL_write(%d, %p, %uz) failed",
476                                c->socket.fd, buf, size);
477     }
478 
479     return n;
480 }
481 
482 
483 static void
484 nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
485 {
486     int                 ret, mode;
487     SSL                 *s;
488     nxt_err_t           err;
489     nxt_int_t           n;
490     nxt_bool_t          quiet, once;
491     nxt_conn_t          *c;
492     nxt_work_handler_t  handler;
493     nxt_openssl_conn_t  *ssltls;
494 
495     c = obj;
496 
497     nxt_debug(task, "openssl conn shutdown");
498 
499     ssltls = c->u.ssltls;
500     s = ssltls->session;
501 
502     if (s == NULL) {
503         handler = c->write_state->close_handler;
504         goto done;
505     }
506 
507     mode = SSL_get_shutdown(s);
508 
509     if (c->socket.timedout || c->socket.error != 0) {
510         quiet = 1;
511 
512     } else if (c->socket.closed && !(mode & SSL_RECEIVED_SHUTDOWN)) {
513         quiet = 1;
514 
515     } else {
516         quiet = 0;
517     }
518 
519     SSL_set_quiet_shutdown(s, quiet);
520 
521     once = 1;
522 
523     for ( ;; ) {
524         SSL_set_shutdown(s, mode);
525 
526         ret = SSL_shutdown(s);
527 
528         err = (ret <= 0) ? nxt_socket_errno : 0;
529 
530         nxt_debug(task, "SSL_shutdown(%d, %d, %b): %d err:%d",
531                   c->socket.fd, mode, quiet, ret, err);
532 
533         if (ret > 0) {
534             /* ret == 1, the shutdown was successfully completed. */
535             handler = c->write_state->close_handler;
536             goto done;
537         }
538 
539         if (ret == 0) {
540             /*
541              * If SSL_shutdown() returns 0 then it should be called
542              * again.  The second SSL_shutdown() call should returns
543              * -1/SSL_ERROR_WANT_READ or -1/SSL_ERROR_WANT_WRITE.
544              * OpenSSL prior to 0.9.8m version however never returns
545              * -1 at all.  Fortunately, OpenSSL internals preserve
546              * correct status available via SSL_get_error(-1).
547              */
548             if (once) {
549                 mode = SSL_get_shutdown(s);
550                 once = 0;
551                 continue;
552             }
553 
554             ret = -1;
555         }
556 
557         /* ret == -1 */
558 
559         break;
560     }
561 
562     n = nxt_openssl_conn_test_error(task, c, ret, err,
563                                     nxt_openssl_conn_io_shutdown);
564 
565     if (nxt_fast_path(n == 0)) {
566         return;
567     }
568 
569     if (n != NXT_ERROR) {  /* n == NXT_AGAIN */
570         c->socket.error_handler = c->read_state->error_handler;
571         nxt_timer_add(task->thread->engine, &c->read_timer, 5000);
572         return;
573     }
574 
575     nxt_openssl_conn_error(c, err, "SSL_shutdown(%d) failed", c->socket.fd);
576 
577     handler = c->write_state->error_handler;
578 
579 done:
580 
581     nxt_work_queue_add(c->write_work_queue, handler, task, c, data);
582 }
583 
584 
585 static nxt_int_t
586 nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret,
587     nxt_err_t sys_err, nxt_work_handler_t handler)
588 {
589     u_long              lib_err;
590     nxt_work_queue_t    *wq;
591     nxt_openssl_conn_t  *ssltls;
592 
593     ssltls = c->u.ssltls;
594 
595     ssltls->ssl_error = SSL_get_error(ssltls->session, ret);
596 
597     nxt_log_debug(c->socket.log, "SSL_get_error(): %d", ssltls->ssl_error);
598 
599     switch (ssltls->ssl_error) {
600 
601     case SSL_ERROR_WANT_READ:
602         nxt_fd_event_block_write(task->thread->engine, &c->socket);
603 
604         c->socket.read_ready = 0;
605         c->socket.read_handler = handler;
606 
607         if (nxt_fd_event_is_disabled(c->socket.read)) {
608             nxt_fd_event_enable_read(task->thread->engine, &c->socket);
609         }
610 
611         return NXT_AGAIN;
612 
613     case SSL_ERROR_WANT_WRITE:
614         nxt_fd_event_block_read(task->thread->engine, &c->socket);
615 
616         c->socket.write_ready = 0;
617         c->socket.write_handler = handler;
618 
619         if (nxt_fd_event_is_disabled(c->socket.write)) {
620             nxt_fd_event_enable_write(task->thread->engine, &c->socket);
621         }
622 
623         return NXT_AGAIN;
624 
625     case SSL_ERROR_SYSCALL:
626 
627         lib_err = ERR_peek_error();
628 
629         nxt_debug(task, "ERR_peek_error(): %l", lib_err);
630 
631         if (sys_err != 0 || lib_err != 0) {
632             return NXT_ERROR;
633         }
634 
635         /* A connection was just closed. */
636         c->socket.closed = 1;
637 
638         /* Fall through. */
639 
640     case SSL_ERROR_ZERO_RETURN:
641         /* A "close notify" alert. */
642 
643         if (c->read_state != NULL) {
644             wq = c->read_work_queue;
645             handler = c->read_state->close_handler;
646 
647         } else {
648             wq = c->write_work_queue;
649             handler = c->write_state->close_handler;
650         }
651 
652         nxt_work_queue_add(wq, handler, task, c, c->socket.data);
653 
654         return 0;
655 
656     default: /* SSL_ERROR_SSL, etc. */
657         c->socket.error = 1000;  /* Nonexistent errno code. */
658         return NXT_ERROR;
659     }
660 }
661 
662 
663 static void nxt_cdecl
664 nxt_openssl_conn_error(nxt_conn_t *c, nxt_err_t err, const char *fmt, ...)
665 {
666     u_char      *p, *end;
667     va_list     args;
668     nxt_uint_t  level;
669     u_char      msg[NXT_MAX_ERROR_STR];
670 
671     c->socket.error = err;
672     level = nxt_openssl_log_error_level(c, err);
673 
674     if (nxt_log_level_enough(c->socket.log, level)) {
675 
676         end = msg + sizeof(msg);
677 
678         va_start(args, fmt);
679         p = nxt_vsprintf(msg, end, fmt, args);
680         va_end(args);
681 
682         if (err != 0) {
683             p = nxt_sprintf(p, end, " %E", err);
684         }
685 
686         p = nxt_openssl_copy_error(p, end);
687 
688         nxt_log_error(level, c->socket.log, "%*s", p - msg, msg);
689 
690     } else {
691         ERR_clear_error();
692     }
693 }
694 
695 
696 static nxt_uint_t
697 nxt_openssl_log_error_level(nxt_conn_t *c, nxt_err_t err)
698 {
699     switch (ERR_GET_REASON(ERR_peek_error())) {
700 
701     case 0:
702         return nxt_socket_error_level(err);
703 
704     case SSL_R_BAD_CHANGE_CIPHER_SPEC:                    /*  103 */
705     case SSL_R_BLOCK_CIPHER_PAD_IS_WRONG:                 /*  129 */
706     case SSL_R_DIGEST_CHECK_FAILED:                       /*  149 */
707     case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:             /*  151 */
708     case SSL_R_EXCESSIVE_MESSAGE_SIZE:                    /*  152 */
709     case SSL_R_LENGTH_MISMATCH:                           /*  159 */
710     case SSL_R_NO_CIPHERS_PASSED:                         /*  182 */
711     case SSL_R_NO_CIPHERS_SPECIFIED:                      /*  183 */
712     case SSL_R_NO_COMPRESSION_SPECIFIED:                  /*  187 */
713     case SSL_R_NO_SHARED_CIPHER:                          /*  193 */
714     case SSL_R_RECORD_LENGTH_MISMATCH:                    /*  213 */
715 #ifdef SSL_R_PARSE_TLSEXT
716     case SSL_R_PARSE_TLSEXT:                              /*  227 */
717 #endif
718     case SSL_R_UNEXPECTED_MESSAGE:                        /*  244 */
719     case SSL_R_UNEXPECTED_RECORD:                         /*  245 */
720     case SSL_R_UNKNOWN_ALERT_TYPE:                        /*  246 */
721     case SSL_R_UNKNOWN_PROTOCOL:                          /*  252 */
722     case SSL_R_WRONG_VERSION_NUMBER:                      /*  267 */
723     case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:       /*  281 */
724 #ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
725     case SSL_R_RENEGOTIATE_EXT_TOO_LONG:                  /*  335 */
726     case SSL_R_RENEGOTIATION_ENCODING_ERR:                /*  336 */
727     case SSL_R_RENEGOTIATION_MISMATCH:                    /*  337 */
728 #endif
729 #ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
730     case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:      /*  338 */
731 #endif
732 #ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
733     case SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING:          /*  345 */
734 #endif
735     case 1000:/* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
736     case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:            /* 1010 */
737     case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:                /* 1020 */
738     case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:             /* 1021 */
739     case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:               /* 1022 */
740     case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:         /* 1030 */
741     case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:             /* 1040 */
742     case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:             /* 1047 */
743         break;
744 
745     case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:                /* 1041 */
746     case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:               /* 1042 */
747     case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:       /* 1043 */
748     case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:           /* 1044 */
749     case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:           /* 1045 */
750     case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:           /* 1046 */
751     case SSL_R_TLSV1_ALERT_UNKNOWN_CA:                    /* 1048 */
752     case SSL_R_TLSV1_ALERT_ACCESS_DENIED:                 /* 1049 */
753     case SSL_R_TLSV1_ALERT_DECODE_ERROR:                  /* 1050 */
754     case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:                 /* 1051 */
755     case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:            /* 1060 */
756     case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:              /* 1070 */
757     case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:         /* 1071 */
758     case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:                /* 1080 */
759     case SSL_R_TLSV1_ALERT_USER_CANCELLED:                /* 1090 */
760     case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:              /* 1100 */
761         return NXT_LOG_ERR;
762 
763     default:
764         return NXT_LOG_ALERT;
765     }
766 
767     return NXT_LOG_INFO;
768 }
769 
770 
771 static void nxt_cdecl
772 nxt_openssl_log_error(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...)
773 {
774     u_char   *p, *end;
775     va_list  args;
776     u_char   msg[NXT_MAX_ERROR_STR];
777 
778     end = msg + sizeof(msg);
779 
780     va_start(args, fmt);
781     p = nxt_vsprintf(msg, end, fmt, args);
782     va_end(args);
783 
784     p = nxt_openssl_copy_error(p, end);
785 
786     nxt_log_error(level, log, "%*s", p - msg, msg);
787 }
788 
789 
790 static u_char *
791 nxt_openssl_copy_error(u_char *p, u_char *end)
792 {
793     int         flags;
794     u_long      err;
795     nxt_bool_t  clear;
796     const char  *data, *delimiter;
797 
798     err = ERR_peek_error();
799     if (err == 0) {
800         return p;
801     }
802 
803     /* Log the most relevant error message ... */
804     data = ERR_reason_error_string(err);
805 
806     p = nxt_sprintf(p, end, " (%d: %s) (OpenSSL: ", ERR_GET_REASON(err), data);
807 
808     /*
809      * ... followed by all queued cumbersome OpenSSL
810      * error messages and drain the error queue.
811      */
812     delimiter = "";
813     clear = 0;
814 
815     for ( ;; ) {
816         err = ERR_get_error_line_data(NULL, NULL, &data, &flags);
817         if (err == 0) {
818             break;
819         }
820 
821         p = nxt_sprintf(p, end, "%s", delimiter);
822 
823         ERR_error_string_n(err, (char *) p, end - p);
824 
825         while (p < end && *p != '\0') {
826             p++;
827         }
828 
829         if ((flags & ERR_TXT_STRING) != 0) {
830             p = nxt_sprintf(p, end, ":%s", data);
831         }
832 
833         clear |= ((flags & ERR_TXT_MALLOCED) != 0);
834 
835         delimiter = "; ";
836     }
837 
838     /* Deallocate additional data. */
839 
840     if (clear) {
841         ERR_clear_error();
842     }
843 
844     if (p < end) {
845         *p++ = ')';
846     }
847 
848     return p;
849 }
850