- Timestamp:
- May 30, 2016, 5:21:21 PM (6 years ago)
- Branches:
- asyncio, debian/master, debian/stretch-backports, master, proxy-ticket, upstream
- Children:
- 2a1ffd6
- Parents:
- c05780e
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/gnutls_ocsp.c
rc05780e rd35b98e 16 16 17 17 #include "gnutls_ocsp.h" 18 19 18 #include "mod_gnutls.h" 20 #include "apr_lib.h" 19 20 #include <apr_lib.h> 21 #include <apr_time.h> 22 #include <gnutls/ocsp.h> 23 #include <time.h> 21 24 22 25 #ifdef APLOG_USE_MODULE … … 24 27 #endif 25 28 29 30 31 #define _log_one_ocsp_fail(s, c) \ 32 ap_log_cerror(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (c), \ 33 "Reason for failed OCSP response verification: %s", (s)) 34 /* 35 * Log all matching reasons for verification failure 36 */ 37 static void _log_verify_fail_reason(const unsigned int verify, conn_rec *c) 38 { 39 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND) 40 _log_one_ocsp_fail("Signer cert not found", c); 41 42 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR) 43 _log_one_ocsp_fail("Signer cert keyusage error", c); 44 45 if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER) 46 _log_one_ocsp_fail("Signer cert is not trusted", c); 47 48 if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) 49 _log_one_ocsp_fail("Insecure algorithm", c); 50 51 if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE) 52 _log_one_ocsp_fail("Signature failure", c); 53 54 if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED) 55 _log_one_ocsp_fail("Signer cert not yet activated", c); 56 57 if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED) 58 _log_one_ocsp_fail("Signer cert expired", c); 59 } 60 61 62 26 63 const char *mgs_store_ocsp_response_path(cmd_parms *parms, 27 64 void *dummy __attribute__((unused)), … … 34 71 return NULL; 35 72 } 73 74 75 76 /** 77 * Check if the provided OCSP response is usable for stapling in this 78 * connection context. Returns GNUTLS_E_SUCCESS if yes. 79 */ 80 int check_ocsp_response(mgs_handle_t *ctxt, const gnutls_datum_t *ocsp_response) 81 { 82 if (ctxt->sc->certs_x509_chain_num < 2) 83 { 84 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 85 "No CA certificates in store, cannot verify response."); 86 return GNUTLS_E_NO_CERTIFICATE_FOUND; 87 } 88 gnutls_x509_trust_list_t issuer; 89 int ret = gnutls_x509_trust_list_init(&issuer, 1); 90 if (ret != GNUTLS_E_SUCCESS) 91 { 92 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 93 "Could not create issuer trust list: %s (%d)", 94 gnutls_strerror(ret), ret); 95 goto trust_cleanup; 96 } 97 /* Only the direct issuer may sign the OCSP response or an OCSP 98 * signer. Assuming the certificate file is properly ordered, it 99 * should be the one directly after the server's. */ 100 ret = gnutls_x509_trust_list_add_cas(issuer, 101 &(ctxt->sc->certs_x509_crt_chain[1]), 102 1, 0); 103 if (ret != 1) 104 { 105 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 106 "Could not populate issuer trust list."); 107 ret = GNUTLS_E_CERTIFICATE_ERROR; 108 goto trust_cleanup; 109 } 110 111 gnutls_ocsp_resp_t resp; 112 ret = gnutls_ocsp_resp_init(&resp); 113 if (ret != GNUTLS_E_SUCCESS) 114 { 115 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 116 "Could not initialize OCSP response structure: %s (%d)", 117 gnutls_strerror(ret), ret); 118 goto resp_cleanup; 119 } 120 ret = gnutls_ocsp_resp_import(resp, ocsp_response); 121 if (ret != GNUTLS_E_SUCCESS) 122 { 123 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 124 "Importing OCSP response failed: %s (%d)", 125 gnutls_strerror(ret), ret); 126 goto resp_cleanup; 127 } 128 129 ret = gnutls_ocsp_resp_check_crt(resp, 0, 130 ctxt->sc->certs_x509_crt_chain[0]); 131 if (ret != GNUTLS_E_SUCCESS) 132 { 133 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 134 "OCSP response is not for server certificate: %s (%d)", 135 gnutls_strerror(ret), ret); 136 goto resp_cleanup; 137 } 138 139 unsigned int verify; 140 ret = gnutls_ocsp_resp_verify(resp, issuer, &verify, 0); 141 if (ret != GNUTLS_E_SUCCESS) 142 { 143 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 144 "OCSP response verification failed: %s (%d)", 145 gnutls_strerror(ret), ret); 146 goto resp_cleanup; 147 } 148 else 149 { 150 /* verification worked, check the result */ 151 if (verify != 0) 152 { 153 _log_verify_fail_reason(verify, ctxt->c); 154 ret = GNUTLS_E_OCSP_RESPONSE_ERROR; 155 goto resp_cleanup; 156 } 157 else 158 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c, 159 "OCSP response is valid."); 160 } 161 162 /* OK, response is for our certificate and valid, let's get the 163 * actual response data. */ 164 unsigned int cert_status; 165 time_t this_update; 166 time_t next_update; 167 ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL, 168 &cert_status, &this_update, 169 &next_update, NULL, NULL); 170 if (ret != GNUTLS_E_SUCCESS) 171 { 172 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 173 "Could not get OCSP response data: %s (%d)", 174 gnutls_strerror(ret), ret); 175 goto resp_cleanup; 176 } 177 178 apr_time_t now = apr_time_now(); 179 apr_time_t valid_at; 180 apr_time_ansi_put(&valid_at, this_update); 181 /* Buffer for human-readable times produced by apr_rfc822_date, 182 * see apr_time.h */ 183 char date_str[APR_RFC822_DATE_LEN]; 184 apr_rfc822_date(date_str, valid_at); 185 186 if (now < valid_at) 187 { 188 /* We don't know if our clock or that of the OCSP responder is 189 * out of sync, so warn but continue. */ 190 ap_log_cerror(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, ctxt->c, 191 "OSCP response claims to be from future (%s), check " 192 "time synchronization!", date_str); 193 } 194 195 if (next_update == (time_t) -1) 196 ap_log_cerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ctxt->c, 197 "OSCP response does not contain nextUpdate info."); 198 else 199 { 200 apr_time_t valid_to; 201 apr_time_ansi_put(&valid_to, next_update); 202 if (now > valid_to) 203 { 204 apr_rfc822_date(date_str, valid_to); 205 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 206 "OCSP response has expired at %s!", date_str); 207 ret = GNUTLS_E_OCSP_RESPONSE_ERROR; 208 goto resp_cleanup; 209 } 210 } 211 212 /* What's the actual status? Will be one of 213 * gnutls_ocsp_cert_status_t as defined in gnutls/ocsp.h. */ 214 if (cert_status == GNUTLS_OCSP_CERT_GOOD) 215 { 216 /* Yay, everything's good! */ 217 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c, 218 "CA flagged certificate as valid at %s.", date_str); 219 } 220 else 221 { 222 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c, 223 "CA flagged certificate as %s at %s.", 224 cert_status == GNUTLS_OCSP_CERT_REVOKED ? 225 "revoked" : "unknown", date_str); 226 ret = GNUTLS_E_OCSP_RESPONSE_ERROR; 227 } 228 229 resp_cleanup: 230 gnutls_ocsp_resp_deinit(resp); 231 trust_cleanup: 232 /* deinit trust list, but not the certificates */ 233 gnutls_x509_trust_list_deinit(issuer, 0); 234 return ret; 235 } 236 237 36 238 37 239 int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)), … … 50 252 "Loading OCSP response failed: %s (%d)", 51 253 gnutls_strerror(ret), ret); 52 gnutls_free(ocsp_response->data); 53 ocsp_response->size = 0; 54 ocsp_response->data = NULL; 55 return GNUTLS_E_NO_CERTIFICATE_STATUS; 56 } 57 58 return GNUTLS_E_SUCCESS; 59 } 254 goto resp_cleanup; 255 } 256 257 /* succeed if response is present and valid, fail otherwise. */ 258 if (check_ocsp_response(ctxt, ocsp_response) == GNUTLS_E_SUCCESS) 259 return GNUTLS_E_SUCCESS; 260 261 resp_cleanup: 262 gnutls_free(ocsp_response->data); 263 ocsp_response->size = 0; 264 ocsp_response->data = NULL; 265 return GNUTLS_E_NO_CERTIFICATE_STATUS; 266 }
Note: See TracChangeset
for help on using the changeset viewer.