/src/mosquitto/lib/net_mosq_ocsp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2009-2021 Roger Light <roger@atchoo.org> |
3 | | Copyright (c) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG), Dr. Lars Voelker <lars.voelker@bmw.de> |
4 | | |
5 | | All rights reserved. This program and the accompanying materials |
6 | | are made available under the terms of the Eclipse Public License 2.0 |
7 | | and Eclipse Distribution License v1.0 which accompany this distribution. |
8 | | |
9 | | The Eclipse Public License is available at |
10 | | https://www.eclipse.org/legal/epl-2.0/ |
11 | | and the Eclipse Distribution License is available at |
12 | | http://www.eclipse.org/org/documents/edl-v10.php. |
13 | | |
14 | | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
15 | | |
16 | | Contributors: |
17 | | Dr. Lars Voelker, BMW AG |
18 | | */ |
19 | | |
20 | | /* |
21 | | COPYRIGHT AND PERMISSION NOTICE of curl on which the ocsp code is based: |
22 | | |
23 | | Copyright (c) 1996 - 2016, Daniel Stenberg, <daniel@haxx.se>, and many |
24 | | contributors, see the THANKS file. |
25 | | |
26 | | All rights reserved. |
27 | | |
28 | | Permission to use, copy, modify, and distribute this software for any purpose |
29 | | with or without fee is hereby granted, provided that the above copyright |
30 | | notice and this permission notice appear in all copies. |
31 | | |
32 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
33 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
34 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN |
35 | | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
36 | | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
37 | | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE |
38 | | OR OTHER DEALINGS IN THE SOFTWARE. |
39 | | |
40 | | Except as contained in this notice, the name of a copyright holder shall not |
41 | | be used in advertising or otherwise to promote the sale, use or other dealings |
42 | | in this Software without prior written authorization of the copyright holder. |
43 | | */ |
44 | | |
45 | | #include "config.h" |
46 | | |
47 | | #ifdef WITH_TLS |
48 | | #include <logging_mosq.h> |
49 | | #include <mosquitto_internal.h> |
50 | | #include <net_mosq.h> |
51 | | |
52 | | #include <openssl/safestack.h> |
53 | | #include <openssl/tls1.h> |
54 | | #include <openssl/ssl.h> |
55 | | #include <openssl/ocsp.h> |
56 | | |
57 | | int mosquitto__verify_ocsp_status_cb(SSL * ssl, void *arg) |
58 | 0 | { |
59 | 0 | struct mosquitto *mosq = (struct mosquitto *)arg; |
60 | 0 | int ocsp_status, result2, i; |
61 | 0 | unsigned char *p; |
62 | 0 | const unsigned char *cp; |
63 | 0 | OCSP_RESPONSE *rsp = NULL; |
64 | 0 | OCSP_BASICRESP *br = NULL; |
65 | 0 | X509_STORE *st = NULL; |
66 | 0 | STACK_OF(X509) *ch = NULL; |
67 | 0 | long len; |
68 | |
|
69 | 0 | UNUSED(ssl); |
70 | |
|
71 | 0 | len = SSL_get_tlsext_status_ocsp_resp(mosq->ssl, &p); |
72 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL_get_tlsext_status_ocsp_resp returned %ld bytes", len); |
73 | | |
74 | | /* the following functions expect a const pointer */ |
75 | 0 | cp = (const unsigned char *)p; |
76 | |
|
77 | 0 | if (!cp || len <= 0) { |
78 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: no response"); |
79 | 0 | goto end; |
80 | 0 | } |
81 | | |
82 | | |
83 | 0 | rsp = d2i_OCSP_RESPONSE(NULL, &cp, len); |
84 | 0 | if (rsp==NULL) { |
85 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response"); |
86 | 0 | goto end; |
87 | 0 | } |
88 | | |
89 | 0 | ocsp_status = OCSP_response_status(rsp); |
90 | 0 | if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { |
91 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid status: %s (%d)", |
92 | 0 | OCSP_response_status_str(ocsp_status), ocsp_status); |
93 | 0 | goto end; |
94 | 0 | } |
95 | | |
96 | 0 | br = OCSP_response_get1_basic(rsp); |
97 | 0 | if (!br) { |
98 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: invalid response"); |
99 | 0 | goto end; |
100 | 0 | } |
101 | | |
102 | 0 | ch = SSL_get_peer_cert_chain(mosq->ssl); |
103 | 0 | if (sk_X509_num(ch) <= 0) { |
104 | 0 | log__printf(mosq, MOSQ_LOG_ERR, "OCSP: we did not receive certificates of the server (num: %d)", sk_X509_num(ch)); |
105 | 0 | goto end; |
106 | 0 | } |
107 | | |
108 | 0 | st = SSL_CTX_get_cert_store(mosq->ssl_ctx); |
109 | | |
110 | | /* Note: |
111 | | * Other checkers often fix problems in OpenSSL before 1.0.2a (e.g. libcurl). |
112 | | * For all currently supported versions of the OpenSSL project, this is not needed anymore. |
113 | | */ |
114 | |
|
115 | 0 | if ((result2=OCSP_basic_verify(br, ch, st, 0)) <= 0) { |
116 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: response verification failed (error: %d)", result2); |
117 | 0 | goto end; |
118 | 0 | } |
119 | | |
120 | 0 | for(i = 0; i < OCSP_resp_count(br); i++) { |
121 | 0 | int cert_status, crl_reason; |
122 | 0 | OCSP_SINGLERESP *single = NULL; |
123 | |
|
124 | 0 | ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; |
125 | |
|
126 | 0 | single = OCSP_resp_get0(br, i); |
127 | 0 | if(!single) |
128 | 0 | continue; |
129 | | |
130 | 0 | cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, &thisupd, &nextupd); |
131 | |
|
132 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate status: %s (%d)", |
133 | 0 | OCSP_cert_status_str(cert_status), cert_status); |
134 | |
|
135 | 0 | switch(cert_status) { |
136 | 0 | case V_OCSP_CERTSTATUS_GOOD: |
137 | | /* Note: A OCSP stapling result will be accepted up to 5 minutes after it expired! */ |
138 | 0 | if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { |
139 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: OCSP response has expired"); |
140 | 0 | goto end; |
141 | 0 | } |
142 | 0 | break; |
143 | | |
144 | 0 | case V_OCSP_CERTSTATUS_REVOKED: |
145 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation reason: %s (%d)", |
146 | 0 | OCSP_crl_reason_str(crl_reason), crl_reason); |
147 | 0 | goto end; |
148 | | |
149 | 0 | case V_OCSP_CERTSTATUS_UNKNOWN: |
150 | 0 | goto end; |
151 | | |
152 | 0 | default: |
153 | 0 | log__printf(mosq, MOSQ_LOG_DEBUG, "OCSP: SSL certificate revocation status unknown"); |
154 | 0 | goto end; |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | 0 | if (br!=NULL) OCSP_BASICRESP_free(br); |
159 | 0 | if (rsp!=NULL) OCSP_RESPONSE_free(rsp); |
160 | 0 | return 1; /* OK */ |
161 | | |
162 | 0 | end: |
163 | 0 | if (br!=NULL) OCSP_BASICRESP_free(br); |
164 | 0 | if (rsp!=NULL) OCSP_RESPONSE_free(rsp); |
165 | 0 | return 0; /* Not OK */ |
166 | 0 | } |
167 | | #endif |