OLD | NEW |
| 1 /* |
| 2 * Copyright 2016 The Netty Project |
| 3 * |
| 4 * The Netty Project licenses this file to you under the Apache License, |
| 5 * version 2.0 (the "License"); you may not use this file except in compliance |
| 6 * with the License. You may obtain a copy of the License at: |
| 7 * |
| 8 * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 * |
| 10 * Unless required by applicable law or agreed to in writing, software |
| 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 * License for the specific language governing permissions and limitations |
| 14 * under the License. |
| 15 */ |
1 /* Licensed to the Apache Software Foundation (ASF) under one or more | 16 /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 * contributor license agreements. See the NOTICE file distributed with | 17 * contributor license agreements. See the NOTICE file distributed with |
3 * this work for additional information regarding copyright ownership. | 18 * this work for additional information regarding copyright ownership. |
4 * The ASF licenses this file to You under the Apache License, Version 2.0 | 19 * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 * (the "License"); you may not use this file except in compliance with | 20 * (the "License"); you may not use this file except in compliance with |
6 * the License. You may obtain a copy of the License at | 21 * the License. You may obtain a copy of the License at |
7 * | 22 * |
8 * http://www.apache.org/licenses/LICENSE-2.0 | 23 * http://www.apache.org/licenses/LICENSE-2.0 |
9 * | 24 * |
10 * Unless required by applicable law or agreed to in writing, software | 25 * Unless required by applicable law or agreed to in writing, software |
11 * distributed under the License is distributed on an "AS IS" BASIS, | 26 * distributed under the License is distributed on an "AS IS" BASIS, |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 27 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 * See the License for the specific language governing permissions and | 28 * See the License for the specific language governing permissions and |
14 * limitations under the License. | 29 * limitations under the License. |
15 */ | 30 */ |
16 | 31 |
17 /** SSL Utilities | |
18 * | |
19 * @author Mladen Turk | |
20 * @version $Id: sslutils.c 1658728 2015-02-10 14:45:19Z kkolinko $ | |
21 */ | |
22 | |
23 #include "tcn.h" | 32 #include "tcn.h" |
24 | 33 |
25 #ifdef HAVE_OPENSSL | |
26 #include "apr_poll.h" | |
27 #include "ssl_private.h" | 34 #include "ssl_private.h" |
28 | 35 |
29 #ifdef WIN32 | |
30 extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data); | |
31 #endif | |
32 | |
33 #ifdef HAVE_OPENSSL_OCSP | |
34 #include <openssl/bio.h> | |
35 #include <openssl/ocsp.h> | |
36 /* defines with the values as seen by the asn1parse -dump openssl command */ | |
37 #define ASN1_SEQUENCE 0x30 | |
38 #define ASN1_OID 0x06 | |
39 #define ASN1_STRING 0x86 | |
40 #pragma message("Using OCSP") | |
41 static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx); | |
42 static int ssl_ocsp_request(X509 *cert, X509 *issuer); | |
43 #endif | |
44 | |
45 /* _________________________________________________________________ | 36 /* _________________________________________________________________ |
46 ** | 37 ** |
47 ** Additional High-Level Functions for OpenSSL | 38 ** Additional High-Level Functions for OpenSSL |
48 ** _________________________________________________________________ | 39 ** _________________________________________________________________ |
49 */ | 40 */ |
50 | 41 |
| 42 |
| 43 /* |
| 44 * Adapted from OpenSSL: |
| 45 * http://osxr.org/openssl/source/ssl/ssl_locl.h#0291 |
| 46 */ |
| 47 /* Bits for algorithm_mkey (key exchange algorithm) */ |
| 48 #define SSL_kRSA 0x00000001L /* RSA key exchange */ |
| 49 #define SSL_kDHr 0x00000002L /* DH cert, RSA CA cert */ /* no such cipher
suites supported! */ |
| 50 #define SSL_kDHd 0x00000004L /* DH cert, DSA CA cert */ /* no such cipher
suite supported! */ |
| 51 #define SSL_kEDH 0x00000008L /* tmp DH key no DH cert */ |
| 52 #define SSL_kKRB5 0x00000010L /* Kerberos5 key exchange */ |
| 53 #define SSL_kECDHr 0x00000020L /* ECDH cert, RSA CA cert */ |
| 54 #define SSL_kECDHe 0x00000040L /* ECDH cert, ECDSA CA cert */ |
| 55 #define SSL_kEECDH 0x00000080L /* ephemeral ECDH */ |
| 56 #define SSL_kPSK 0x00000100L /* PSK */ |
| 57 #define SSL_kGOST 0x00000200L /* GOST key exchange */ |
| 58 #define SSL_kSRP 0x00000400L /* SRP */ |
| 59 |
| 60 /* Bits for algorithm_auth (server authentication) */ |
| 61 #define SSL_aRSA 0x00000001L /* RSA auth */ |
| 62 #define SSL_aDSS 0x00000002L /* DSS auth */ |
| 63 #define SSL_aNULL 0x00000004L /* no auth (i.e. use ADH or AECDH) */ |
| 64 #define SSL_aDH 0x00000008L /* Fixed DH auth (kDHd or kDHr) */ /* no suc
h ciphersuites supported! */ |
| 65 #define SSL_aECDH 0x00000010L /* Fixed ECDH auth (kECDHe or kECDHr) */ |
| 66 #define SSL_aKRB5 0x00000020L /* KRB5 auth */ |
| 67 #define SSL_aECDSA 0x00000040L /* ECDSA auth*/ |
| 68 #define SSL_aPSK 0x00000080L /* PSK auth */ |
| 69 #define SSL_aGOST94 0x00000100L /* GOST R 34.10-94 signature auth */ |
| 70 #define SSL_aGOST01 0x00000200L /* GOST R 34.10-2001 signature auth */ |
| 71 |
| 72 const char* TCN_UNKNOWN_AUTH_METHOD = "UNKNOWN"; |
| 73 |
| 74 /* OpenSSL end */ |
| 75 |
| 76 /* |
| 77 * Adapted from Android: |
| 78 * https://android.googlesource.com/platform/external/openssl/+/master/patches/0
003-jsse.patch |
| 79 */ |
| 80 const char* SSL_cipher_authentication_method(const SSL_CIPHER* cipher){ |
| 81 #ifndef OPENSSL_IS_BORINGSSL |
| 82 switch (cipher->algorithm_mkey) |
| 83 { |
| 84 case SSL_kRSA: |
| 85 return SSL_TXT_RSA; |
| 86 case SSL_kDHr: |
| 87 return SSL_TXT_DH "_" SSL_TXT_RSA; |
| 88 |
| 89 case SSL_kDHd: |
| 90 return SSL_TXT_DH "_" SSL_TXT_DSS; |
| 91 case SSL_kEDH: |
| 92 switch (cipher->algorithm_auth) |
| 93 { |
| 94 case SSL_aDSS: |
| 95 return "DHE_" SSL_TXT_DSS; |
| 96 case SSL_aRSA: |
| 97 return "DHE_" SSL_TXT_RSA; |
| 98 case SSL_aNULL: |
| 99 return SSL_TXT_DH "_anon"; |
| 100 default: |
| 101 return TCN_UNKNOWN_AUTH_METHOD; |
| 102 } |
| 103 case SSL_kKRB5: |
| 104 return SSL_TXT_KRB5; |
| 105 case SSL_kECDHr: |
| 106 return SSL_TXT_ECDH "_" SSL_TXT_RSA; |
| 107 case SSL_kECDHe: |
| 108 return SSL_TXT_ECDH "_" SSL_TXT_ECDSA; |
| 109 case SSL_kEECDH: |
| 110 switch (cipher->algorithm_auth) |
| 111 { |
| 112 case SSL_aECDSA: |
| 113 return "ECDHE_" SSL_TXT_ECDSA; |
| 114 case SSL_aRSA: |
| 115 return "ECDHE_" SSL_TXT_RSA; |
| 116 case SSL_aNULL: |
| 117 return SSL_TXT_ECDH "_anon"; |
| 118 default: |
| 119 return TCN_UNKNOWN_AUTH_METHOD; |
| 120 } |
| 121 default: |
| 122 return TCN_UNKNOWN_AUTH_METHOD; |
| 123 } |
| 124 #else |
| 125 return SSL_CIPHER_get_kx_name(cipher); |
| 126 #endif |
| 127 |
| 128 } |
| 129 |
51 /* we initialize this index at startup time | 130 /* we initialize this index at startup time |
52 * and never write to it at request time, | 131 * and never write to it at request time, |
53 * so this static is thread safe. | 132 * so this static is thread safe. |
54 * also note that OpenSSL increments at static variable when | 133 * also note that OpenSSL increments at static variable when |
55 * SSL_get_ex_new_index() is called, so we _must_ do this at startup. | 134 * SSL_get_ex_new_index() is called, so we _must_ do this at startup. |
56 */ | 135 */ |
57 static int SSL_app_data2_idx = -1; | 136 static int SSL_app_data2_idx = -1; |
58 static int SSL_app_data3_idx = -1; | 137 static int SSL_app_data3_idx = -1; |
59 void SSL_init_app_data2_3_idx(void) | 138 static int SSL_app_data4_idx = -1; |
| 139 void SSL_init_app_data_idx() |
60 { | 140 { |
61 int i; | 141 int i; |
62 | 142 |
63 if (SSL_app_data2_idx > -1) { | 143 if (SSL_app_data2_idx == -1) { |
64 return; | 144 /* we _do_ need to call this two times */ |
| 145 for (i = 0; i <= 1; i++) { |
| 146 SSL_app_data2_idx = SSL_get_ex_new_index(0, "tcn_ssl_ctxt_t*", NULL,
NULL, NULL); |
| 147 } |
65 } | 148 } |
66 | 149 |
67 /* we _do_ need to call this two times */ | 150 if (SSL_app_data3_idx == -1) { |
68 for (i = 0; i <= 1; i++) { | 151 SSL_app_data3_idx = SSL_get_ex_new_index(0, "int* handshakeCount", NULL,
NULL, NULL); |
69 SSL_app_data2_idx = | |
70 SSL_get_ex_new_index(0, | |
71 "Second Application Data for SSL", | |
72 NULL, NULL, NULL); | |
73 } | 152 } |
74 | 153 |
75 if (SSL_app_data3_idx > -1) { | 154 if (SSL_app_data4_idx == -1) { |
76 return; | 155 SSL_app_data4_idx = SSL_get_ex_new_index(0, "tcn_ssl_verify_config_t*",
NULL, NULL, NULL); |
77 } | 156 } |
78 | |
79 SSL_app_data3_idx = | |
80 SSL_get_ex_new_index(0, | |
81 "Third Application Data for SSL", | |
82 NULL, NULL, NULL); | |
83 } | 157 } |
84 | 158 |
85 void *SSL_get_app_data2(SSL *ssl) | 159 void *SSL_get_app_data2(SSL *ssl) |
86 { | 160 { |
87 return (void *)SSL_get_ex_data(ssl, SSL_app_data2_idx); | 161 return (void *)SSL_get_ex_data(ssl, SSL_app_data2_idx); |
88 } | 162 } |
89 | 163 |
90 void SSL_set_app_data2(SSL *ssl, void *arg) | 164 void SSL_set_app_data2(SSL *ssl, void *arg) |
91 { | 165 { |
92 SSL_set_ex_data(ssl, SSL_app_data2_idx, (char *)arg); | 166 SSL_set_ex_data(ssl, SSL_app_data2_idx, (char *)arg); |
93 return; | 167 return; |
94 } | 168 } |
95 | 169 |
96 void *SSL_get_app_data3(SSL *ssl) | 170 void *SSL_get_app_data3(SSL *ssl) |
97 { | 171 { |
98 return SSL_get_ex_data(ssl, SSL_app_data3_idx); | 172 return SSL_get_ex_data(ssl, SSL_app_data3_idx); |
99 } | 173 } |
100 | 174 |
101 void SSL_set_app_data3(SSL *ssl, void *arg) | 175 void SSL_set_app_data3(SSL *ssl, void *arg) |
102 { | 176 { |
103 SSL_set_ex_data(ssl, SSL_app_data3_idx, arg); | 177 SSL_set_ex_data(ssl, SSL_app_data3_idx, arg); |
104 } | 178 } |
105 | 179 |
106 /* Simple echo password prompting */ | 180 void *SSL_get_app_data4(SSL *ssl) |
107 int SSL_password_prompt(tcn_pass_cb_t *data) | |
108 { | 181 { |
109 int rv = 0; | 182 return SSL_get_ex_data(ssl, SSL_app_data4_idx); |
110 data->password[0] = '\0'; | 183 } |
111 if (data->cb.obj) { | 184 |
112 JNIEnv *e; | 185 void SSL_set_app_data4(SSL *ssl, void *arg) |
113 jobject o; | 186 { |
114 jstring prompt; | 187 SSL_set_ex_data(ssl, SSL_app_data4_idx, arg); |
115 tcn_get_java_env(&e); | |
116 prompt = AJP_TO_JSTRING(data->prompt); | |
117 if ((o = (*e)->CallObjectMethod(e, data->cb.obj, | |
118 data->cb.mid[0], prompt))) { | |
119 TCN_ALLOC_CSTRING(o); | |
120 if (J2S(o)) { | |
121 strncpy(data->password, J2S(o), SSL_MAX_PASSWORD_LEN); | |
122 data->password[SSL_MAX_PASSWORD_LEN-1] = '\0'; | |
123 rv = (int)strlen(data->password); | |
124 } | |
125 TCN_FREE_CSTRING(o); | |
126 } | |
127 } | |
128 else { | |
129 #ifdef WIN32 | |
130 rv = WIN32_SSL_password_prompt(data); | |
131 #elif !defined(OPENSSL_IS_BORINGSSL) | |
132 EVP_read_pw_string(data->password, SSL_MAX_PASSWORD_LEN, | |
133 data->prompt, 0); | |
134 #endif | |
135 rv = (int)strlen(data->password); | |
136 } | |
137 if (rv > 0) { | |
138 /* Remove LF char if present */ | |
139 char *r = strchr(data->password, '\n'); | |
140 if (r) { | |
141 *r = '\0'; | |
142 rv--; | |
143 } | |
144 #ifdef WIN32 | |
145 if ((r = strchr(data->password, '\r'))) { | |
146 *r = '\0'; | |
147 rv--; | |
148 } | |
149 #endif | |
150 } | |
151 return rv; | |
152 } | 188 } |
153 | 189 |
154 int SSL_password_callback(char *buf, int bufsiz, int verify, | 190 int SSL_password_callback(char *buf, int bufsiz, int verify, |
155 void *cb) | 191 void *cb) |
156 { | 192 { |
157 tcn_pass_cb_t *cb_data = (tcn_pass_cb_t *)cb; | 193 char *password = (char *) cb; |
158 | 194 |
159 if (buf == NULL) | 195 if (buf == NULL || password == NULL) |
160 return 0; | 196 return 0; |
161 *buf = '\0'; | 197 *buf = '\0'; |
162 if (cb_data == NULL) | 198 |
163 cb_data = &tcn_password_callback; | 199 if (password[0]) { |
164 if (!cb_data->prompt) | |
165 cb_data->prompt = SSL_DEFAULT_PASS_PROMPT; | |
166 if (cb_data->password[0]) { | |
167 /* Return already obtained password */ | 200 /* Return already obtained password */ |
168 strncpy(buf, cb_data->password, bufsiz); | 201 strncpy(buf, password, bufsiz); |
169 buf[bufsiz - 1] = '\0'; | |
170 return (int)strlen(buf); | |
171 } | 202 } |
172 else { | 203 |
173 if (SSL_password_prompt(cb_data) > 0) | |
174 strncpy(buf, cb_data->password, bufsiz); | |
175 } | |
176 buf[bufsiz - 1] = '\0'; | 204 buf[bufsiz - 1] = '\0'; |
177 return (int)strlen(buf); | 205 return (int)strlen(buf); |
178 } | 206 } |
179 | 207 |
| 208 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED) ||
defined(LIBRESSL_VERSION_NUMBER) |
| 209 |
180 static unsigned char dh0512_p[]={ | 210 static unsigned char dh0512_p[]={ |
181 0xD9,0xBA,0xBF,0xFD,0x69,0x38,0xC9,0x51,0x2D,0x19,0x37,0x39, | 211 0xD9,0xBA,0xBF,0xFD,0x69,0x38,0xC9,0x51,0x2D,0x19,0x37,0x39, |
182 0xD7,0x7D,0x7E,0x3E,0x25,0x58,0x55,0x94,0x90,0x60,0x93,0x7A, | 212 0xD7,0x7D,0x7E,0x3E,0x25,0x58,0x55,0x94,0x90,0x60,0x93,0x7A, |
183 0xF2,0xD5,0x61,0x5F,0x06,0xE8,0x08,0xB4,0x57,0xF4,0xCF,0xB4, | 213 0xF2,0xD5,0x61,0x5F,0x06,0xE8,0x08,0xB4,0x57,0xF4,0xCF,0xB4, |
184 0x41,0xCC,0xC4,0xAC,0xD4,0xF0,0x45,0x88,0xC9,0xD1,0x21,0x4C, | 214 0x41,0xCC,0xC4,0xAC,0xD4,0xF0,0x45,0x88,0xC9,0xD1,0x21,0x4C, |
185 0xB6,0x72,0x48,0xBD,0x73,0x80,0xE0,0xDD,0x88,0x41,0xA0,0xF1, | 215 0xB6,0x72,0x48,0xBD,0x73,0x80,0xE0,0xDD,0x88,0x41,0xA0,0xF1, |
186 0xEA,0x4B,0x71,0x13 | 216 0xEA,0x4B,0x71,0x13 |
187 }; | 217 }; |
188 static unsigned char dh1024_p[]={ | 218 static unsigned char dh1024_p[]={ |
189 0xA2,0x95,0x7E,0x7C,0xA9,0xD5,0x55,0x1D,0x7C,0x77,0x11,0xAC, | 219 0xA2,0x95,0x7E,0x7C,0xA9,0xD5,0x55,0x1D,0x7C,0x77,0x11,0xAC, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 0x3E,0x19,0xBD,0xE2,0x80,0x11,0x86,0xC7,0x4B,0x7F,0x67,0x86, | 296 0x3E,0x19,0xBD,0xE2,0x80,0x11,0x86,0xC7,0x4B,0x7F,0x67,0x86, |
267 0x47,0xD2,0x38,0xCD,0x8F,0xFE,0x65,0x3C,0x11,0xCD,0x96,0x99, | 297 0x47,0xD2,0x38,0xCD,0x8F,0xFE,0x65,0x3C,0x11,0xCD,0x96,0x99, |
268 0x4E,0x45,0xEB,0xEC,0x1D,0x94,0x8C,0x53, | 298 0x4E,0x45,0xEB,0xEC,0x1D,0x94,0x8C,0x53, |
269 }; | 299 }; |
270 static unsigned char dhxxx2_g[]={ | 300 static unsigned char dhxxx2_g[]={ |
271 0x02 | 301 0x02 |
272 }; | 302 }; |
273 | 303 |
274 static DH *get_dh(int idx) | 304 static DH *get_dh(int idx) |
275 { | 305 { |
276 #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED) | |
277 DH *dh; | 306 DH *dh; |
278 | |
279 if ((dh = DH_new()) == NULL) | 307 if ((dh = DH_new()) == NULL) |
280 return NULL; | 308 return NULL; |
281 switch (idx) { | 309 switch (idx) { |
282 case SSL_TMP_KEY_DH_512: | 310 case SSL_TMP_KEY_DH_512: |
283 dh->p = BN_bin2bn(dh0512_p, sizeof(dh0512_p), NULL); | 311 dh->p = BN_bin2bn(dh0512_p, sizeof(dh0512_p), NULL); |
284 break; | 312 break; |
285 case SSL_TMP_KEY_DH_1024: | 313 case SSL_TMP_KEY_DH_1024: |
286 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); | 314 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); |
287 break; | 315 break; |
288 case SSL_TMP_KEY_DH_2048: | 316 case SSL_TMP_KEY_DH_2048: |
289 dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); | 317 dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); |
290 break; | 318 break; |
291 case SSL_TMP_KEY_DH_4096: | 319 case SSL_TMP_KEY_DH_4096: |
292 dh->p = BN_bin2bn(dh4096_p, sizeof(dh2048_p), NULL); | 320 dh->p = BN_bin2bn(dh4096_p, sizeof(dh2048_p), NULL); |
293 break; | 321 break; |
294 } | 322 } |
295 dh->g = BN_bin2bn(dhxxx2_g, sizeof(dhxxx2_g), NULL); | 323 dh->g = BN_bin2bn(dhxxx2_g, sizeof(dhxxx2_g), NULL); |
296 if ((dh->p == NULL) || (dh->g == NULL)) { | 324 if ((dh->p == NULL) || (dh->g == NULL)) { |
297 DH_free(dh); | 325 DH_free(dh); |
298 return NULL; | 326 return NULL; |
299 } | 327 } |
300 else | 328 else |
301 return dh; | 329 return dh; |
| 330 return NULL; |
| 331 } |
302 #else | 332 #else |
| 333 static DH *get_dh(int idx) |
| 334 { |
303 return NULL; | 335 return NULL; |
| 336 } |
304 #endif | 337 #endif |
305 } | |
306 | 338 |
307 DH *SSL_dh_get_tmp_param(int key_len) | 339 DH *SSL_dh_get_tmp_param(int key_len) |
308 { | 340 { |
309 DH *dh; | 341 DH *dh; |
310 | 342 |
311 if (key_len == 512) | 343 if (key_len == 512) |
312 dh = get_dh(SSL_TMP_KEY_DH_512); | 344 dh = get_dh(SSL_TMP_KEY_DH_512); |
313 else if (key_len == 1024) | 345 else if (key_len == 1024) |
314 dh = get_dh(SSL_TMP_KEY_DH_1024); | 346 dh = get_dh(SSL_TMP_KEY_DH_1024); |
315 else if (key_len == 2048) | 347 else if (key_len == 2048) |
316 dh = get_dh(SSL_TMP_KEY_DH_2048); | 348 dh = get_dh(SSL_TMP_KEY_DH_2048); |
317 else if (key_len == 4096) | 349 else if (key_len == 4096) |
318 dh = get_dh(SSL_TMP_KEY_DH_4096); | 350 dh = get_dh(SSL_TMP_KEY_DH_4096); |
319 else | 351 else |
320 dh = get_dh(SSL_TMP_KEY_DH_1024); | 352 dh = get_dh(SSL_TMP_KEY_DH_1024); |
321 return dh; | 353 return dh; |
322 } | 354 } |
323 | 355 |
324 DH *SSL_dh_get_param_from_file(const char *file) | |
325 { | |
326 DH *dh = NULL; | |
327 BIO *bio; | |
328 | |
329 if ((bio = BIO_new_file(file, "r")) == NULL) | |
330 return NULL; | |
331 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); | |
332 BIO_free(bio); | |
333 return dh; | |
334 } | |
335 | |
336 /* | |
337 * Handle out temporary RSA private keys on demand | |
338 * | |
339 * The background of this as the TLSv1 standard explains it: | |
340 * | |
341 * | D.1. Temporary RSA keys | |
342 * | | |
343 * | US Export restrictions limit RSA keys used for encryption to 512 | |
344 * | bits, but do not place any limit on lengths of RSA keys used for | |
345 * | signing operations. Certificates often need to be larger than 512 | |
346 * | bits, since 512-bit RSA keys are not secure enough for high-value | |
347 * | transactions or for applications requiring long-term security. Some | |
348 * | certificates are also designated signing-only, in which case they | |
349 * | cannot be used for key exchange. | |
350 * | | |
351 * | When the public key in the certificate cannot be used for encryption, | |
352 * | the server signs a temporary RSA key, which is then exchanged. In | |
353 * | exportable applications, the temporary RSA key should be the maximum | |
354 * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are | |
355 * | relatively insecure, they should be changed often. For typical | |
356 * | electronic commerce applications, it is suggested that keys be | |
357 * | changed daily or every 500 transactions, and more often if possible. | |
358 * | Note that while it is acceptable to use the same temporary key for | |
359 * | multiple transactions, it must be signed each time it is used. | |
360 * | | |
361 * | RSA key generation is a time-consuming process. In many cases, a | |
362 * | low-priority process can be assigned the task of key generation. | |
363 * | Whenever a new key is completed, the existing temporary key can be | |
364 * | replaced with the new one. | |
365 * | |
366 * XXX: base on comment above, if thread support is enabled, | |
367 * we should spawn a low-priority thread to generate new keys | |
368 * on the fly. | |
369 * | |
370 * So we generated 512 and 1024 bit temporary keys on startup | |
371 * which we now just hand out on demand.... | |
372 */ | |
373 | |
374 RSA *SSL_callback_tmp_RSA(SSL *ssl, int export, int keylen) | |
375 { | |
376 int idx; | |
377 | |
378 /* doesn't matter if export flag is on, | |
379 * we won't be asked for keylen > 512 in that case. | |
380 * if we are asked for a keylen > 1024, it is too expensive | |
381 * to generate on the fly. | |
382 */ | |
383 | |
384 switch (keylen) { | |
385 case 512: | |
386 idx = SSL_TMP_KEY_RSA_512; | |
387 break; | |
388 case 2048: | |
389 idx = SSL_TMP_KEY_RSA_2048; | |
390 if (SSL_temp_keys[idx] == NULL) | |
391 idx = SSL_TMP_KEY_RSA_1024; | |
392 break; | |
393 case 4096: | |
394 idx = SSL_TMP_KEY_RSA_4096; | |
395 if (SSL_temp_keys[idx] == NULL) | |
396 idx = SSL_TMP_KEY_RSA_2048; | |
397 break; | |
398 case 1024: | |
399 default: | |
400 idx = SSL_TMP_KEY_RSA_1024; | |
401 break; | |
402 } | |
403 return (RSA *)SSL_temp_keys[idx]; | |
404 } | |
405 | |
406 /* | 356 /* |
407 * Hand out the already generated DH parameters... | 357 * Hand out the already generated DH parameters... |
408 */ | 358 */ |
409 DH *SSL_callback_tmp_DH(SSL *ssl, int export, int keylen) | 359 DH *SSL_callback_tmp_DH(SSL *ssl, int export, int keylen) |
410 { | 360 { |
411 int idx; | 361 int idx; |
412 switch (keylen) { | 362 switch (keylen) { |
413 case 512: | 363 case 512: |
414 idx = SSL_TMP_KEY_DH_512; | 364 idx = SSL_TMP_KEY_DH_512; |
415 break; | 365 break; |
416 case 2048: | 366 case 2048: |
417 idx = SSL_TMP_KEY_DH_2048; | 367 idx = SSL_TMP_KEY_DH_2048; |
418 break; | 368 break; |
419 case 4096: | 369 case 4096: |
420 idx = SSL_TMP_KEY_DH_4096; | 370 idx = SSL_TMP_KEY_DH_4096; |
421 break; | 371 break; |
422 case 1024: | 372 case 1024: |
423 default: | 373 default: |
424 idx = SSL_TMP_KEY_DH_1024; | 374 idx = SSL_TMP_KEY_DH_1024; |
425 break; | 375 break; |
426 } | 376 } |
427 return (DH *)SSL_temp_keys[idx]; | 377 return (DH *)SSL_temp_keys[idx]; |
428 } | 378 } |
429 | 379 |
| 380 DH *SSL_callback_tmp_DH_512(SSL *ssl, int export, int keylen) |
| 381 { |
| 382 return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_512]; |
| 383 } |
| 384 |
| 385 DH *SSL_callback_tmp_DH_1024(SSL *ssl, int export, int keylen) |
| 386 { |
| 387 return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_1024]; |
| 388 } |
| 389 |
| 390 DH *SSL_callback_tmp_DH_2048(SSL *ssl, int export, int keylen) |
| 391 { |
| 392 return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_2048]; |
| 393 } |
| 394 |
| 395 DH *SSL_callback_tmp_DH_4096(SSL *ssl, int export, int keylen) |
| 396 { |
| 397 return (DH *)SSL_temp_keys[SSL_TMP_KEY_DH_4096]; |
| 398 } |
| 399 |
430 /* | 400 /* |
431 * Read a file that optionally contains the server certificate in PEM | 401 * Read a file that optionally contains the server certificate in PEM |
432 * format, possibly followed by a sequence of CA certificates that | 402 * format, possibly followed by a sequence of CA certificates that |
433 * should be sent to the peer in the SSL Certificate message. | 403 * should be sent to the peer in the SSL Certificate message. |
434 */ | 404 */ |
435 int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file, | 405 int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, const char *file, bool skipfirst
) |
436 int skipfirst) | |
437 { | 406 { |
438 BIO *bio; | 407 BIO *bio; |
439 int n; | 408 int n; |
440 | 409 |
441 if ((bio = BIO_new(BIO_s_file())) == NULL) | 410 if ((bio = BIO_new(BIO_s_file())) == NULL) |
442 return -1; | 411 return -1; |
443 if (BIO_read_filename(bio, file) <= 0) { | 412 if (BIO_read_filename(bio, file) <= 0) { |
444 BIO_free(bio); | 413 BIO_free(bio); |
445 return -1; | 414 return -1; |
446 } | 415 } |
447 n = SSL_CTX_use_certificate_chain_bio(ctx, bio, skipfirst); | 416 n = SSL_CTX_use_certificate_chain_bio(ctx, bio, skipfirst); |
448 BIO_free(bio); | 417 BIO_free(bio); |
449 return n; | 418 return n; |
450 } | 419 } |
451 | 420 |
452 int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio, | 421 static int SSL_CTX_setup_certs(SSL_CTX *ctx, BIO *bio, bool skipfirst, bool ca) |
453 int skipfirst) | |
454 { | 422 { |
455 X509 *x509; | 423 X509 *x509; |
456 unsigned long err; | 424 unsigned long err; |
457 int n; | 425 int n; |
458 | 426 |
459 /* optionally skip a leading server certificate */ | 427 /* optionally skip a leading server certificate */ |
460 if (skipfirst) { | 428 if (skipfirst) { |
461 if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { | 429 if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { |
462 return -1; | 430 return -1; |
463 } | 431 } |
464 X509_free(x509); | 432 X509_free(x509); |
465 } | 433 } |
466 | 434 |
467 /* free a perhaps already configured extra chain */ | 435 n = 0; |
468 SSL_CTX_clear_extra_chain_certs(ctx); | 436 if (ca) { |
| 437 while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 438 if (SSL_CTX_add_client_CA(ctx, x509) != 1) { |
| 439 X509_free(x509); |
| 440 return -1; |
| 441 } |
| 442 // SSL_CTX_add_client_CA does not take ownership of the x509. It jus
t calls X509_get_subject_name |
| 443 // and make a duplicate of this value. So we should always free the
x509 after this call. |
| 444 // See https://github.com/netty/netty/issues/6249. |
| 445 X509_free(x509); |
| 446 n++; |
| 447 } |
| 448 } else { |
| 449 /* free a perhaps already configured extra chain */ |
| 450 SSL_CTX_clear_extra_chain_certs(ctx); |
| 451 |
| 452 /* create new extra chain by loading the certs */ |
| 453 while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
| 454 // SSL_CTX_add_extra_chain_cert transfers ownership of the x509 cert
ificate if the method succeeds. |
| 455 if (SSL_CTX_add_extra_chain_cert(ctx, x509) != 1) { |
| 456 X509_free(x509); |
| 457 return -1; |
| 458 } |
| 459 n++; |
| 460 } |
| 461 } |
| 462 |
| 463 /* Make sure that only the error is just an EOF */ |
| 464 if ((err = ERR_peek_error()) > 0) { |
| 465 if (!( ERR_GET_LIB(err) == ERR_LIB_PEM |
| 466 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { |
| 467 return -1; |
| 468 } |
| 469 ERR_clear_error(); |
| 470 } |
| 471 return n; |
| 472 } |
| 473 |
| 474 int SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO *bio, bool skipfirst) |
| 475 { |
| 476 return SSL_CTX_setup_certs(ctx, bio, skipfirst, false); |
| 477 } |
| 478 |
| 479 |
| 480 int SSL_CTX_use_client_CA_bio(SSL_CTX *ctx, BIO *bio) |
| 481 { |
| 482 return SSL_CTX_setup_certs(ctx, bio, false, true); |
| 483 } |
| 484 |
| 485 int SSL_use_certificate_chain_bio(SSL *ssl, BIO *bio, bool skipfirst) |
| 486 { |
| 487 #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) |
| 488 // Only supported on openssl 1.0.2+ |
| 489 return -1; |
| 490 #else |
| 491 X509 *x509; |
| 492 unsigned long err; |
| 493 int n; |
| 494 |
| 495 /* optionally skip a leading server certificate */ |
| 496 if (skipfirst) { |
| 497 if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { |
| 498 return -1; |
| 499 } |
| 500 X509_free(x509); |
| 501 } |
469 | 502 |
470 /* create new extra chain by loading the certs */ | 503 /* create new extra chain by loading the certs */ |
471 n = 0; | 504 n = 0; |
| 505 |
472 while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { | 506 while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) { |
473 if (SSL_CTX_add_extra_chain_cert(ctx, x509) != 1) { | 507 if (SSL_add0_chain_cert(ssl, x509) != 1) { |
474 X509_free(x509); | 508 X509_free(x509); |
475 return -1; | 509 return -1; |
476 } | 510 } |
477 n++; | 511 n++; |
478 } | 512 } |
479 /* Make sure that only the error is just an EOF */ | 513 /* Make sure that only the error is just an EOF */ |
480 if ((err = ERR_peek_error()) > 0) { | 514 if ((err = ERR_peek_error()) > 0) { |
481 if (!( ERR_GET_LIB(err) == ERR_LIB_PEM | 515 if (!( ERR_GET_LIB(err) == ERR_LIB_PEM |
482 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { | 516 && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { |
483 return -1; | 517 return -1; |
484 } | 518 } |
485 while (ERR_get_error() > 0) ; | 519 ERR_clear_error(); |
486 } | 520 } |
487 return n; | 521 return n; |
| 522 #endif |
488 } | 523 } |
489 | 524 |
490 static int ssl_X509_STORE_lookup(X509_STORE *store, int yype, | 525 X509 *load_pem_cert_bio(const char *password, const BIO *bio) |
491 X509_NAME *name, X509_OBJECT *obj) | |
492 { | 526 { |
493 X509_STORE_CTX ctx; | 527 X509 *cert = PEM_read_bio_X509_AUX((BIO*) bio, NULL, |
494 int rc; | 528 (pem_password_cb *)SSL_password_callback, |
495 | 529 (void *)password); |
496 X509_STORE_CTX_init(&ctx, store, NULL, NULL); | 530 if (cert == NULL && |
497 rc = X509_STORE_get_by_subject(&ctx, yype, name, obj); | 531 (ERR_GET_REASON(ERR_peek_last_error()) == PEM_R_NO_START_LINE)) { |
498 X509_STORE_CTX_cleanup(&ctx); | 532 ERR_clear_error(); |
499 return rc; | 533 BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL); |
| 534 cert = d2i_X509_bio((BIO*) bio, NULL); |
| 535 } |
| 536 return cert; |
500 } | 537 } |
501 | 538 |
502 static int ssl_verify_CRL(int ok, X509_STORE_CTX *ctx, tcn_ssl_ctxt_t *c) | 539 EVP_PKEY *load_pem_key_bio(const char *password, const BIO *bio) |
503 { | 540 { |
504 X509_OBJECT obj; | 541 EVP_PKEY *key = PEM_read_bio_PrivateKey((BIO*) bio, NULL, |
505 X509_NAME *subject, *issuer; | 542 (pem_password_cb *)SSL_password_callback, |
506 X509 *cert; | 543 (void *)password); |
507 X509_CRL *crl; | |
508 EVP_PKEY *pubkey; | |
509 int i, n, rc; | |
510 | 544 |
511 /* | 545 BIO_ctrl((BIO*) bio, BIO_CTRL_RESET, 0, NULL); |
512 * Determine certificate ingredients in advance | 546 return key; |
513 */ | 547 } |
514 cert = X509_STORE_CTX_get_current_cert(ctx); | |
515 subject = X509_get_subject_name(cert); | |
516 issuer = X509_get_issuer_name(cert); | |
517 | 548 |
518 /* | 549 int tcn_EVP_PKEY_up_ref(EVP_PKEY* pkey) { |
519 * OpenSSL provides the general mechanism to deal with CRLs but does not | 550 #if defined(OPENSSL_IS_BORINGSSL) |
520 * use them automatically when verifying certificates, so we do it | 551 // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89# |
521 * explicitly here. We will check the CRL for the currently checked | 552 EVP_PKEY_up_ref(pkey); |
522 * certificate, if there is such a CRL in the store. | 553 return 1; |
523 * | 554 #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) |
524 * We come through this procedure for each certificate in the certificate | 555 return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); |
525 * chain, starting with the root-CA's certificate. At each step we've to | 556 #else |
526 * both verify the signature on the CRL (to make sure it's a valid CRL) | 557 return EVP_PKEY_up_ref(pkey); |
527 * and it's revocation list (to make sure the current certificate isn't | 558 #endif |
528 * revoked). But because to check the signature on the CRL we need the | 559 } |
529 * public key of the issuing CA certificate (which was already processed | |
530 * one round before), we've a little problem. But we can both solve it and | |
531 * at the same time optimize the processing by using the following | |
532 * verification scheme (idea and code snippets borrowed from the GLOBUS | |
533 * project): | |
534 * | |
535 * 1. We'll check the signature of a CRL in each step when we find a CRL | |
536 * through the _subject_ name of the current certificate. This CRL | |
537 * itself will be needed the first time in the next round, of course. | |
538 * But we do the signature processing one round before this where the | |
539 * public key of the CA is available. | |
540 * | |
541 * 2. We'll check the revocation list of a CRL in each step when | |
542 * we find a CRL through the _issuer_ name of the current certificate. | |
543 * This CRLs signature was then already verified one round before. | |
544 * | |
545 * This verification scheme allows a CA to revoke its own certificate as | |
546 * well, of course. | |
547 */ | |
548 | 560 |
549 /* | 561 int tcn_X509_up_ref(X509* cert) { |
550 * Try to retrieve a CRL corresponding to the _subject_ of | 562 #if defined(OPENSSL_IS_BORINGSSL) |
551 * the current certificate in order to verify it's integrity. | 563 // Workaround for https://bugs.chromium.org/p/boringssl/issues/detail?id=89# |
552 */ | 564 X509_up_ref(cert); |
553 memset((char *)&obj, 0, sizeof(obj)); | 565 return 1; |
554 rc = ssl_X509_STORE_lookup(c->crl, | 566 #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) |
555 X509_LU_CRL, subject, &obj); | 567 return CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); |
556 crl = obj.data.crl; | 568 #else |
| 569 return X509_up_ref(cert); |
| 570 #endif |
| 571 } |
557 | 572 |
558 if ((rc > 0) && crl) { | 573 int tcn_set_verify_config(tcn_ssl_verify_config_t* c, jint tcn_mode, jint depth)
{ |
559 /* | 574 if (depth >= 0) { |
560 * Log information about CRL | 575 c->verify_depth = depth; |
561 * (A little bit complicated because of ASN.1 and BIOs...) | |
562 */ | |
563 /* | |
564 * Verify the signature on this CRL | |
565 */ | |
566 pubkey = X509_get_pubkey(cert); | |
567 rc = X509_CRL_verify(crl, pubkey); | |
568 /* Only refcounted in OpenSSL */ | |
569 if (pubkey) | |
570 EVP_PKEY_free(pubkey); | |
571 if (rc <= 0) { | |
572 /* TODO: Log Invalid signature on CRL */ | |
573 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); | |
574 X509_OBJECT_free_contents(&obj); | |
575 return 0; | |
576 } | |
577 | |
578 /* | |
579 * Check date of CRL to make sure it's not expired | |
580 */ | |
581 i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl)); | |
582 | |
583 if (i == 0) { | |
584 /* TODO: Log Found CRL has invalid nextUpdate field */ | |
585 | |
586 X509_STORE_CTX_set_error(ctx, | |
587 X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); | |
588 X509_OBJECT_free_contents(&obj); | |
589 return 0; | |
590 } | |
591 | |
592 if (i < 0) { | |
593 /* TODO: Log Found CRL is expired */ | |
594 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED); | |
595 X509_OBJECT_free_contents(&obj); | |
596 | |
597 return 0; | |
598 } | |
599 | |
600 X509_OBJECT_free_contents(&obj); | |
601 } | 576 } |
602 | 577 |
603 /* | 578 switch (tcn_mode) { |
604 * Try to retrieve a CRL corresponding to the _issuer_ of | 579 case SSL_CVERIFY_IGNORED: |
605 * the current certificate in order to check for revocation. | 580 switch (c->verify_mode) { |
606 */ | 581 case SSL_CVERIFY_NONE: |
607 memset((char *)&obj, 0, sizeof(obj)); | 582 return SSL_VERIFY_NONE; |
608 rc = ssl_X509_STORE_lookup(c->crl, | 583 case SSL_CVERIFY_OPTIONAL: |
609 X509_LU_CRL, issuer, &obj); | 584 return SSL_VERIFY_PEER; |
610 | 585 default: |
611 crl = obj.data.crl; | 586 return (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); |
612 if ((rc > 0) && crl) { | |
613 /* | |
614 * Check if the current certificate is revoked by this CRL | |
615 */ | |
616 n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); | |
617 | |
618 for (i = 0; i < n; i++) { | |
619 X509_REVOKED *revoked = | |
620 sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); | |
621 | |
622 ASN1_INTEGER *sn = revoked->serialNumber; | |
623 | |
624 if (!ASN1_INTEGER_cmp(sn, X509_get_serialNumber(cert))) { | |
625 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); | |
626 X509_OBJECT_free_contents(&obj); | |
627 | |
628 return 0; | |
629 } | |
630 } | 587 } |
631 | 588 case SSL_CVERIFY_NONE: |
632 X509_OBJECT_free_contents(&obj); | 589 c->verify_mode = SSL_CVERIFY_NONE; |
| 590 return SSL_VERIFY_NONE; |
| 591 case SSL_CVERIFY_OPTIONAL: |
| 592 c->verify_mode = SSL_CVERIFY_OPTIONAL; |
| 593 return SSL_VERIFY_PEER; |
| 594 default: |
| 595 c->verify_mode = SSL_CVERIFY_REQUIRED; |
| 596 return SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; |
633 } | 597 } |
634 | |
635 return ok; | |
636 } | |
637 | |
638 /* | |
639 * This OpenSSL callback function is called when OpenSSL | |
640 * does client authentication and verifies the certificate chain. | |
641 */ | |
642 | |
643 | |
644 int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx) | |
645 { | |
646 /* Get Apache context back through OpenSSL context */ | |
647 SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, | |
648 SSL_get_ex_data_X509_STORE_CTX_idx()); | |
649 tcn_ssl_ctxt_t *c = SSL_get_app_data2(ssl); | |
650 | |
651 /* Get verify ingredients */ | |
652 int errnum = X509_STORE_CTX_get_error(ctx); | |
653 int errdepth = X509_STORE_CTX_get_error_depth(ctx); | |
654 int verify = c->verify_mode; | |
655 int depth = c->verify_depth; | |
656 int skip_crl = 0; | |
657 | |
658 if (verify == SSL_CVERIFY_UNSET || | |
659 verify == SSL_CVERIFY_NONE) | |
660 return 1; | |
661 | |
662 if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) && | |
663 (verify == SSL_CVERIFY_OPTIONAL_NO_CA)) { | |
664 ok = 1; | |
665 SSL_set_verify_result(ssl, X509_V_OK); | |
666 } | |
667 | |
668 #ifdef HAVE_OPENSSL_OCSP | |
669 /* First perform OCSP validation if possible */ | |
670 if (ok) { | |
671 /* If there was an optional verification error, it's not | |
672 * possible to perform OCSP validation since the issuer may be | |
673 * missing/untrusted. Fail in that case. | |
674 */ | |
675 if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum)) { | |
676 X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); | |
677 errnum = X509_V_ERR_APPLICATION_VERIFICATION; | |
678 ok = 0; | |
679 } | |
680 else { | |
681 int ocsp_response = ssl_verify_OCSP(ok, ctx); | |
682 if (ocsp_response == OCSP_STATUS_OK) { | |
683 skip_crl = 1; /* we know it is valid we skip crl evaluation */ | |
684 } | |
685 else if (ocsp_response == OCSP_STATUS_REVOKED) { | |
686 ok = 0 ; | |
687 errnum = X509_STORE_CTX_get_error(ctx); | |
688 } | |
689 else if (ocsp_response == OCSP_STATUS_UNKNOWN) { | |
690 /* TODO: do nothing for time being, continue with CRL */ | |
691 ; | |
692 } | |
693 } | |
694 } | |
695 #endif | |
696 /* | |
697 * Additionally perform CRL-based revocation checks | |
698 */ | |
699 if (ok && c->crl && !skip_crl) { | |
700 if (!(ok = ssl_verify_CRL(ok, ctx, c))) { | |
701 errnum = X509_STORE_CTX_get_error(ctx); | |
702 /* TODO: Log something */ | |
703 } | |
704 } | |
705 /* | |
706 * If we already know it's not ok, log the real reason | |
707 */ | |
708 if (!ok) { | |
709 // Just in case that sslnetwork stuff was used, which is not true for ne
tty but it can't harm to still | |
710 // guard against it. | |
711 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl); | |
712 | |
713 /* TODO: Some logging | |
714 * Certificate Verification: Error | |
715 */ | |
716 if (con != NULL && con->peer) { | |
717 X509_free(con->peer); | |
718 con->peer = NULL; | |
719 } | |
720 } | |
721 if (errdepth > depth) { | |
722 /* TODO: Some logging | |
723 * Certificate Verification: Certificate Chain too long | |
724 */ | |
725 ok = 0; | |
726 } | |
727 return ok; | |
728 } | |
729 | |
730 /* | |
731 * This callback function is executed while OpenSSL processes the SSL | |
732 * handshake and does SSL record layer stuff. It's used to trap | |
733 * client-initiated renegotiations, and for dumping everything to the | |
734 * log. | |
735 */ | |
736 void SSL_callback_handshake(const SSL *ssl, int where, int rc) | |
737 { | |
738 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl); | |
739 | |
740 /* Retrieve the conn_rec and the associated SSLConnRec. */ | |
741 if (con == NULL) { | |
742 return; | |
743 } | |
744 | |
745 | |
746 /* If the reneg state is to reject renegotiations, check the SSL | |
747 * state machine and move to ABORT if a Client Hello is being | |
748 * read. */ | |
749 if ((where & SSL_CB_ACCEPT_LOOP) && con->reneg_state == RENEG_REJECT) { | |
750 int state = SSL_get_state(ssl); | |
751 | |
752 if (state == SSL3_ST_SR_CLNT_HELLO_A | |
753 #ifndef OPENSSL_IS_BORINGSSL | |
754 || state == SSL23_ST_SR_CLNT_HELLO_A | |
755 #endif | |
756 ) { | |
757 con->reneg_state = RENEG_ABORT; | |
758 /* XXX: rejecting client initiated renegotiation | |
759 */ | |
760 } | |
761 } | |
762 /* If the first handshake is complete, change state to reject any | |
763 * subsequent client-initated renegotiation. */ | |
764 else if ((where & SSL_CB_HANDSHAKE_DONE) && con->reneg_state == RENEG_INIT)
{ | |
765 con->reneg_state = RENEG_REJECT; | |
766 } | |
767 | |
768 } | 598 } |
769 | 599 |
770 int SSL_callback_next_protos(SSL *ssl, const unsigned char **data, | 600 int SSL_callback_next_protos(SSL *ssl, const unsigned char **data, |
771 unsigned int *len, void *arg) | 601 unsigned int *len, void *arg) |
772 { | 602 { |
773 tcn_ssl_ctxt_t *ssl_ctxt = arg; | 603 tcn_ssl_ctxt_t *ssl_ctxt = arg; |
774 | 604 |
775 *data = ssl_ctxt->next_proto_data; | 605 *data = ssl_ctxt->next_proto_data; |
776 *len = ssl_ctxt->next_proto_len; | 606 *len = ssl_ctxt->next_proto_len; |
777 | 607 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 void *arg) { | 671 void *arg) { |
842 tcn_ssl_ctxt_t *ssl_ctxt = arg; | 672 tcn_ssl_ctxt_t *ssl_ctxt = arg; |
843 return select_next_proto(ssl, (const unsigned char**) out, outlen, in, inlen
, ssl_ctxt->next_proto_data, ssl_ctxt->next_proto_len, ssl_ctxt->next_selector_f
ailure_behavior); | 673 return select_next_proto(ssl, (const unsigned char**) out, outlen, in, inlen
, ssl_ctxt->next_proto_data, ssl_ctxt->next_proto_len, ssl_ctxt->next_selector_f
ailure_behavior); |
844 } | 674 } |
845 | 675 |
846 int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned
char *outlen, | 676 int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned
char *outlen, |
847 const unsigned char *in, unsigned int inlen, void *arg) { | 677 const unsigned char *in, unsigned int inlen, void *arg) { |
848 tcn_ssl_ctxt_t *ssl_ctxt = arg; | 678 tcn_ssl_ctxt_t *ssl_ctxt = arg; |
849 return select_next_proto(ssl, out, outlen, in, inlen, ssl_ctxt->alpn_proto_d
ata, ssl_ctxt->alpn_proto_len, ssl_ctxt->alpn_selector_failure_behavior); | 679 return select_next_proto(ssl, out, outlen, in, inlen, ssl_ctxt->alpn_proto_d
ata, ssl_ctxt->alpn_proto_len, ssl_ctxt->alpn_selector_failure_behavior); |
850 } | 680 } |
851 | |
852 #ifdef HAVE_OPENSSL_OCSP | |
853 | |
854 /* Function that is used to do the OCSP verification */ | |
855 static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx) | |
856 { | |
857 X509 *cert, *issuer; | |
858 int r = OCSP_STATUS_UNKNOWN; | |
859 | |
860 cert = X509_STORE_CTX_get_current_cert(ctx); | |
861 /* if we can't get the issuer, we cannot perform OCSP verification */ | |
862 if (X509_STORE_CTX_get1_issuer(&issuer, ctx, cert) == 1 ) { | |
863 r = ssl_ocsp_request(cert, issuer); | |
864 if (r == OCSP_STATUS_REVOKED) { | |
865 /* we set the error if we know that it is revoked */ | |
866 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); | |
867 } | |
868 else { | |
869 /* else we return unknown, so that we can continue with the crl */ | |
870 r = OCSP_STATUS_UNKNOWN; | |
871 } | |
872 X509_free(issuer); /* It appears that we should free issuer since | |
873 * X509_STORE_CTX_get1_issuer() calls X509_OBJECT_up_
ref_count() | |
874 * on the issuer object (unline X509_STORE_CTX_get_cu
rrent_cert() | |
875 * that just returns the pointer | |
876 */ | |
877 } | |
878 return r; | |
879 } | |
880 | |
881 | |
882 /* Helps with error handling or realloc */ | |
883 static void *apr_xrealloc(void *buf, size_t oldlen, size_t len, apr_pool_t *p) | |
884 { | |
885 void *newp = apr_palloc(p, len); | |
886 | |
887 if(newp) | |
888 memcpy(newp, buf, oldlen); | |
889 return newp; | |
890 } | |
891 | |
892 /* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables | |
893 returns 0 on success, 1 on failure */ | |
894 static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls, | |
895 int *nocsp_urls, apr_pool_t *p) | |
896 { | |
897 char **new_ocsp_urls, *ocsp_url; | |
898 int len, err = 0, new_nocsp_urls; | |
899 | |
900 if (*asn1 == ASN1_STRING) { | |
901 len = *++asn1; | |
902 asn1++; | |
903 new_nocsp_urls = *nocsp_urls+1; | |
904 if ((new_ocsp_urls = apr_xrealloc(*ocsp_urls,*nocsp_urls, new_nocsp_urls
, p)) == NULL) | |
905 err = 1; | |
906 if (!err) { | |
907 *ocsp_urls = new_ocsp_urls; | |
908 *nocsp_urls = new_nocsp_urls; | |
909 *(*ocsp_urls + *nocsp_urls) = NULL; | |
910 if ((ocsp_url = apr_palloc(p, len + 1)) == NULL) { | |
911 err = 1; | |
912 } | |
913 else { | |
914 memcpy(ocsp_url, asn1, len); | |
915 ocsp_url[len] = '\0'; | |
916 *(*ocsp_urls + *nocsp_urls - 1) = ocsp_url; | |
917 } | |
918 } | |
919 } | |
920 return err; | |
921 | |
922 } | |
923 | |
924 /* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url fu
nction */ | |
925 static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int *nocsp_url
s, apr_pool_t *p) | |
926 { | |
927 int len, err = 0 ; | |
928 const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
0x01}; | |
929 | |
930 len = *++asn1; | |
931 asn1++; | |
932 if (memcmp(asn1, OCSP_OID, len) == 0) { | |
933 asn1+=len; | |
934 err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls, p); | |
935 } | |
936 return err; | |
937 } | |
938 | |
939 | |
940 /* Parses an ASN1 Sequence. It is a recursive function, since if it finds a seq
uence | |
941 within the sequence it calls recursively itself. This function stops when it
finds | |
942 the end of the ASN1 sequence (marked by '\0'), so if there are other sequence
s within | |
943 the same sequence the while loop parses the sequences */ | |
944 | |
945 /* This algo was developed with AIA in mind so it was tested only with this exte
nsion */ | |
946 static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls, | |
947 int *nocsp_urls, apr_pool_t *p) | |
948 { | |
949 int len = 0 , err = 0; | |
950 | |
951 while (!err && *asn1 != '\0') { | |
952 switch(*asn1) { | |
953 case ASN1_SEQUENCE: | |
954 len = *++asn1; | |
955 asn1++; | |
956 err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls, p); | |
957 break; | |
958 case ASN1_OID: | |
959 err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls, p); | |
960 return 0; | |
961 break; | |
962 default: | |
963 err = 1; /* we shouldn't have any errors */ | |
964 break; | |
965 } | |
966 asn1+=len; | |
967 } | |
968 return err; | |
969 } | |
970 | |
971 /* the main function that gets the ASN1 encoding string and returns | |
972 a pointer to a NULL terminated "array" of char *, that contains | |
973 the ocsp_urls */ | |
974 static char **decode_OCSP_url(ASN1_OCTET_STRING *os, apr_pool_t *p) | |
975 { | |
976 char **response = NULL; | |
977 unsigned char *ocsp_urls; | |
978 int len, numofresponses = 0 ; | |
979 | |
980 len = ASN1_STRING_length(os); | |
981 | |
982 ocsp_urls = apr_palloc(p, len + 1); | |
983 memcpy(ocsp_urls,os->data, len); | |
984 ocsp_urls[len] = '\0'; | |
985 | |
986 if ((response = apr_pcalloc(p, sizeof(char *))) == NULL) | |
987 return NULL; | |
988 if (parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses, p)) | |
989 response = NULL; | |
990 return response; | |
991 } | |
992 | |
993 | |
994 /* stolen from openssl ocsp command */ | |
995 static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer, | |
996 STACK_OF(OCSP_CERTID) *ids) | |
997 { | |
998 OCSP_CERTID *id; | |
999 | |
1000 if (!issuer) | |
1001 return 0; | |
1002 if (!*req) | |
1003 *req = OCSP_REQUEST_new(); | |
1004 if (!*req) | |
1005 return 0; | |
1006 id = OCSP_cert_to_id(NULL, cert, issuer); | |
1007 if (!id || !sk_OCSP_CERTID_push(ids, id)) | |
1008 return 0; | |
1009 if (!OCSP_request_add0_id(*req, id)) | |
1010 return 0; | |
1011 else | |
1012 return 1; | |
1013 } | |
1014 | |
1015 | |
1016 /* Creates the APR socket and connect to the hostname. Returns the | |
1017 socket or NULL if there is an error. | |
1018 */ | |
1019 static apr_socket_t *make_socket(char *hostname, int port, apr_pool_t *mp) | |
1020 { | |
1021 apr_sockaddr_t *sa_in; | |
1022 apr_status_t status; | |
1023 apr_socket_t *sock = NULL; | |
1024 | |
1025 | |
1026 status = apr_sockaddr_info_get(&sa_in, hostname, APR_INET, port, 0, mp); | |
1027 | |
1028 if (status == APR_SUCCESS) | |
1029 status = apr_socket_create(&sock, sa_in->family, SOCK_STREAM, APR_PROTO_
TCP, mp); | |
1030 if (status == APR_SUCCESS) | |
1031 status = apr_socket_connect(sock, sa_in); | |
1032 | |
1033 if (status == APR_SUCCESS) | |
1034 return sock; | |
1035 return NULL; | |
1036 } | |
1037 | |
1038 | |
1039 /* Creates the request in a memory BIO in order to send it to the OCSP server. | |
1040 Most parts of this function are taken from mod_ssl support for OCSP (with som
e | |
1041 minor modifications | |
1042 */ | |
1043 static BIO *serialize_request(OCSP_REQUEST *req, char *host, int port, char *pat
h) | |
1044 { | |
1045 BIO *bio; | |
1046 int len; | |
1047 | |
1048 len = i2d_OCSP_REQUEST(req, NULL); | |
1049 | |
1050 bio = BIO_new(BIO_s_mem()); | |
1051 | |
1052 BIO_printf(bio, "POST %s HTTP/1.0\r\n" | |
1053 "Host: %s:%d\r\n" | |
1054 "Content-Type: application/ocsp-request\r\n" | |
1055 "Content-Length: %d\r\n" | |
1056 "\r\n", | |
1057 path, host, port, len); | |
1058 | |
1059 if (i2d_OCSP_REQUEST_bio(bio, req) != 1) { | |
1060 BIO_free(bio); | |
1061 return NULL; | |
1062 } | |
1063 | |
1064 return bio; | |
1065 } | |
1066 | |
1067 | |
1068 /* Send the OCSP request to the OCSP server. Taken from mod_ssl OCSP support */ | |
1069 static int ocsp_send_req(apr_socket_t *sock, BIO *req) | |
1070 { | |
1071 int len; | |
1072 char buf[TCN_BUFFER_SZ]; | |
1073 apr_status_t rv; | |
1074 int ok = 1; | |
1075 | |
1076 while ((len = BIO_read(req, buf, sizeof buf)) > 0) { | |
1077 char *wbuf = buf; | |
1078 apr_size_t remain = len; | |
1079 | |
1080 do { | |
1081 apr_size_t wlen = remain; | |
1082 rv = apr_socket_send(sock, wbuf, &wlen); | |
1083 wbuf += remain; | |
1084 remain -= wlen; | |
1085 } while (rv == APR_SUCCESS && remain > 0); | |
1086 | |
1087 if (rv != APR_SUCCESS) { | |
1088 apr_socket_close(sock); | |
1089 ok = 0; | |
1090 } | |
1091 } | |
1092 | |
1093 return ok; | |
1094 } | |
1095 | |
1096 | |
1097 | |
1098 /* Parses the buffer from the response and extracts the OCSP response. | |
1099 Taken from openssl library */ | |
1100 static OCSP_RESPONSE *parse_ocsp_resp(char *buf, int len) | |
1101 { | |
1102 BIO *mem = NULL; | |
1103 char tmpbuf[1024]; | |
1104 OCSP_RESPONSE *resp = NULL; | |
1105 char *p, *q, *r; | |
1106 int retcode; | |
1107 | |
1108 mem = BIO_new(BIO_s_mem()); | |
1109 if(mem == NULL) | |
1110 return NULL; | |
1111 | |
1112 BIO_write(mem, buf, len); /* write the buffer to the bio */ | |
1113 if (BIO_gets(mem, tmpbuf, 512) <= 0) { | |
1114 OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR); | |
1115 goto err; | |
1116 } | |
1117 /* Parse the HTTP response. This will look like this: | |
1118 * "HTTP/1.0 200 OK". We need to obtain the numeric code and | |
1119 * (optional) informational message. | |
1120 */ | |
1121 | |
1122 /* Skip to first white space (passed protocol info) */ | |
1123 for (p = tmpbuf; *p && !apr_isspace(*p); p++) | |
1124 continue; | |
1125 if (!*p) { | |
1126 goto err; | |
1127 } | |
1128 /* Skip past white space to start of response code */ | |
1129 while (apr_isspace(*p)) | |
1130 p++; | |
1131 if (!*p) { | |
1132 goto err; | |
1133 } | |
1134 /* Find end of response code: first whitespace after start of code */ | |
1135 for (q = p; *q && !apr_isspace(*q); q++) | |
1136 continue; | |
1137 if (!*q) { | |
1138 goto err; | |
1139 } | |
1140 /* Set end of response code and start of message */ | |
1141 *q++ = 0; | |
1142 /* Attempt to parse numeric code */ | |
1143 retcode = strtoul(p, &r, 10); | |
1144 if (*r) | |
1145 goto err; | |
1146 /* Skip over any leading white space in message */ | |
1147 while (apr_isspace(*q)) | |
1148 q++; | |
1149 if (*q) { | |
1150 /* Finally zap any trailing white space in message (include CRLF) */ | |
1151 /* We know q has a non white space character so this is OK */ | |
1152 for(r = q + strlen(q) - 1; apr_isspace(*r); r--) *r = 0; | |
1153 } | |
1154 if (retcode != 200) { | |
1155 goto err; | |
1156 } | |
1157 /* Find blank line marking beginning of content */ | |
1158 while (BIO_gets(mem, tmpbuf, 512) > 0) { | |
1159 for (p = tmpbuf; apr_isspace(*p); p++) | |
1160 continue; | |
1161 if (!*p) | |
1162 break; | |
1163 } | |
1164 if (*p) { | |
1165 goto err; | |
1166 } | |
1167 if (!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) { | |
1168 goto err; | |
1169 } | |
1170 err: | |
1171 BIO_free(mem); | |
1172 return resp; | |
1173 } | |
1174 | |
1175 | |
1176 /* Reads the respnse from the APR socket to a buffer, and parses the buffer to | |
1177 return the OCSP response */ | |
1178 #define ADDLEN 512 | |
1179 static OCSP_RESPONSE *ocsp_get_resp(apr_socket_t *sock) | |
1180 { | |
1181 int buflen; | |
1182 apr_size_t totalread = 0; | |
1183 apr_size_t readlen; | |
1184 char *buf, tmpbuf[ADDLEN]; | |
1185 apr_status_t rv = APR_SUCCESS; | |
1186 apr_pool_t *p; | |
1187 OCSP_RESPONSE *resp; | |
1188 | |
1189 apr_pool_create(&p, NULL); | |
1190 buflen = ADDLEN; | |
1191 buf = apr_palloc(p, buflen); | |
1192 if (buf == NULL) { | |
1193 apr_pool_destroy(p); | |
1194 return NULL; | |
1195 } | |
1196 | |
1197 while (rv == APR_SUCCESS ) { | |
1198 readlen = sizeof(tmpbuf); | |
1199 rv = apr_socket_recv(sock, tmpbuf, &readlen); | |
1200 if (rv == APR_SUCCESS) { /* if we have read something .. we can put it i
n the buffer*/ | |
1201 if ((totalread + readlen) >= buflen) { | |
1202 buf = apr_xrealloc(buf, buflen, buflen + ADDLEN, p); | |
1203 if (buf == NULL) { | |
1204 apr_pool_destroy(p); | |
1205 return NULL; | |
1206 } | |
1207 buflen += ADDLEN; /* if needed we enlarge the buffer */ | |
1208 } | |
1209 memcpy(buf + totalread, tmpbuf, readlen); /* the copy to the buffer
*/ | |
1210 totalread += readlen; /* update the total bytes read */ | |
1211 } | |
1212 else { | |
1213 if (rv == APR_EOF && readlen == 0) | |
1214 ; /* EOF, normal situation */ | |
1215 else if (readlen == 0) { | |
1216 /* Not success, and readlen == 0 .. some error */ | |
1217 apr_pool_destroy(p); | |
1218 return NULL; | |
1219 } | |
1220 } | |
1221 } | |
1222 | |
1223 resp = parse_ocsp_resp(buf, buflen); | |
1224 apr_pool_destroy(p); | |
1225 return resp; | |
1226 } | |
1227 | |
1228 /* Creates and OCSP request and returns the OCSP_RESPONSE */ | |
1229 static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url) | |
1230 { | |
1231 OCSP_RESPONSE *ocsp_resp = NULL; | |
1232 OCSP_REQUEST *ocsp_req = NULL; | |
1233 BIO *bio_req; | |
1234 char *hostname, *path, *c_port; | |
1235 int port, use_ssl; | |
1236 STACK_OF(OCSP_CERTID) *ids = NULL; | |
1237 int ok = 0; | |
1238 apr_socket_t *apr_sock = NULL; | |
1239 apr_pool_t *mp; | |
1240 | |
1241 apr_pool_create(&mp, NULL); | |
1242 ids = sk_OCSP_CERTID_new_null(); | |
1243 | |
1244 /* problem parsing the URL */ | |
1245 if (OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) { | |
1246 sk_OCSP_CERTID_free(ids); | |
1247 return NULL; | |
1248 } | |
1249 | |
1250 /* Create the OCSP request */ | |
1251 if (sscanf(c_port, "%d", &port) != 1) | |
1252 goto end; | |
1253 ocsp_req = OCSP_REQUEST_new(); | |
1254 if (ocsp_req == NULL) | |
1255 return NULL; | |
1256 if (add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 ) | |
1257 goto free_req; | |
1258 | |
1259 /* create the BIO with the request to send */ | |
1260 bio_req = serialize_request(ocsp_req, hostname, port, path); | |
1261 if (bio_req == NULL) { | |
1262 goto free_req; | |
1263 } | |
1264 | |
1265 apr_sock = make_socket(hostname, port, mp); | |
1266 if (apr_sock == NULL) { | |
1267 ocsp_resp = NULL; | |
1268 goto free_bio; | |
1269 } | |
1270 | |
1271 ok = ocsp_send_req(apr_sock, bio_req); | |
1272 if (ok) | |
1273 ocsp_resp = ocsp_get_resp(apr_sock); | |
1274 | |
1275 free_bio: | |
1276 BIO_free(bio_req); | |
1277 | |
1278 free_req: | |
1279 if(apr_sock && ok) /* if ok == 0 we have already closed the socket */ | |
1280 apr_socket_close(apr_sock); | |
1281 | |
1282 apr_pool_destroy(mp); | |
1283 | |
1284 sk_OCSP_CERTID_free(ids); | |
1285 OCSP_REQUEST_free(ocsp_req); | |
1286 | |
1287 end: | |
1288 return ocsp_resp; | |
1289 } | |
1290 | |
1291 /* Process the OCSP_RESPONSE and returns the corresponding | |
1292 answert according to the status. | |
1293 */ | |
1294 static int process_ocsp_response(OCSP_RESPONSE *ocsp_resp) | |
1295 { | |
1296 int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i; | |
1297 OCSP_BASICRESP *bs; | |
1298 OCSP_SINGLERESP *ss; | |
1299 | |
1300 r = OCSP_response_status(ocsp_resp); | |
1301 | |
1302 if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) { | |
1303 OCSP_RESPONSE_free(ocsp_resp); | |
1304 return OCSP_STATUS_UNKNOWN; | |
1305 } | |
1306 bs = OCSP_response_get1_basic(ocsp_resp); | |
1307 | |
1308 ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */ | |
1309 | |
1310 i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL); | |
1311 if (i == V_OCSP_CERTSTATUS_GOOD) | |
1312 o = OCSP_STATUS_OK; | |
1313 else if (i == V_OCSP_CERTSTATUS_REVOKED) | |
1314 o = OCSP_STATUS_REVOKED; | |
1315 else if (i == V_OCSP_CERTSTATUS_UNKNOWN) | |
1316 o = OCSP_STATUS_UNKNOWN; | |
1317 | |
1318 /* we clean up */ | |
1319 OCSP_RESPONSE_free(ocsp_resp); | |
1320 return o; | |
1321 } | |
1322 | |
1323 static int ssl_ocsp_request(X509 *cert, X509 *issuer) | |
1324 { | |
1325 char **ocsp_urls = NULL; | |
1326 int nid; | |
1327 X509_EXTENSION *ext; | |
1328 ASN1_OCTET_STRING *os; | |
1329 apr_pool_t *p; | |
1330 | |
1331 apr_pool_create(&p, NULL); | |
1332 | |
1333 /* Get the proper extension */ | |
1334 nid = X509_get_ext_by_NID(cert,NID_info_access,-1); | |
1335 if (nid >= 0 ) { | |
1336 ext = X509_get_ext(cert,nid); | |
1337 os = X509_EXTENSION_get_data(ext); | |
1338 | |
1339 ocsp_urls = decode_OCSP_url(os, p); | |
1340 } | |
1341 | |
1342 /* if we find the extensions and we can parse it check | |
1343 the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */ | |
1344 if (ocsp_urls != NULL) { | |
1345 OCSP_RESPONSE *resp; | |
1346 /* for the time being just check for the fist response .. a better | |
1347 approach is to iterate for all the possible ocsp urls */ | |
1348 resp = get_ocsp_response(cert, issuer, ocsp_urls[0]); | |
1349 | |
1350 if (resp != NULL) { | |
1351 apr_pool_destroy(p); | |
1352 return process_ocsp_response(resp); | |
1353 } | |
1354 } | |
1355 apr_pool_destroy(p); | |
1356 return OCSP_STATUS_UNKNOWN; | |
1357 } | |
1358 | |
1359 #endif /* HAS_OCSP_ENABLED */ | |
1360 #endif /* HAVE_OPENSSL */ | |
OLD | NEW |