diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 278af8bba..9eacf9f94 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -110,9 +110,91 @@ struct certificate_ocsp { struct ebmb_node key; unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH]; struct chunk response; - + long expire; }; +/* + * This function returns the number of seconds elapsed + * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the + * date presented un ASN1_GENERALIZEDTIME. + * + * In parsing error case, it returns -1. + */ +static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d) +{ + long epoch; + char *p, *end; + const unsigned short month_offset[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; + int year, month; + + if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1; + + p = (char *)d->data; + end = p + d->length; + + if (end - p < 4) return -1; + year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0'; + p += 4; + if (end - p < 2) return -1; + month = 10 * (p[0] - '0') + p[1] - '0'; + if (month < 1 || month > 12) return -1; + /* Compute the number of seconds since 1 jan 1970 and the beginning of current month + We consider leap years and the current month ( '9') + goto nosec; + if (end - p < 2) return -1; + /* Add the seconds of the current minute */ + epoch += 10 * (p[0] - '0') + p[1] - '0'; + p += 2; + if (p == end) return -1; + /* Ignore seconds float part if present */ + if (p[0] == '.') { + do { + if (++p == end) return -1; + } while (p[0] >= '0' && p[0] <= '9'); + } + +nosec: + if (p[0] == 'Z') { + if (end - p != 1) return -1; + return epoch; + } + else if (p[0] == '+') { + if (end - p != 5) return -1; + /* Apply timezone offset */ + return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60; + } + else if (p[0] == '-') { + if (end - p != 5) return -1; + /* Apply timezone offset */ + return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60; + } + + return -1; +} + static struct eb_root cert_ocsp_tree; /* This function starts to check if the OCSP response (in DER format) contained @@ -229,6 +311,8 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi goto out; } + ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW; + ret = 0; out: if (bs) @@ -306,7 +390,8 @@ int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg) if (!ocsp || !ocsp->response.str || - !ocsp->response.len) + !ocsp->response.len || + (ocsp->expire < now.tv_sec)) return SSL_TLSEXT_ERR_NOACK; ssl_buf = OPENSSL_malloc(ocsp->response.len);