| 1610 | } |
| 1611 | |
| 1612 | apr_status_t md_cert_chain_read_http(struct apr_array_header_t *chain, |
| 1613 | apr_pool_t *p, const struct md_http_response_t *res) |
| 1614 | { |
| 1615 | const char *ct = NULL; |
| 1616 | apr_off_t blen; |
| 1617 | apr_size_t data_len = 0; |
| 1618 | char *data; |
| 1619 | md_cert_t *cert; |
| 1620 | apr_status_t rv = APR_ENOENT; |
| 1621 | |
| 1622 | md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, 0, p, |
| 1623 | "chain_read, processing %d response", res->status); |
| 1624 | if (APR_SUCCESS != (rv = apr_brigade_length(res->body, 1, &blen))) goto cleanup; |
| 1625 | if (blen > 1024*1024) { /* certs usually are <2k each */ |
| 1626 | rv = APR_EINVAL; |
| 1627 | goto cleanup; |
| 1628 | } |
| 1629 | |
| 1630 | data_len = (apr_size_t)blen; |
| 1631 | ct = apr_table_get(res->headers, "Content-Type"); |
| 1632 | if (!res->body || !ct) goto cleanup; |
| 1633 | ct = md_util_parse_ct(res->req->pool, ct); |
| 1634 | if (!strcmp("application/pkix-cert", ct)) { |
| 1635 | rv = md_cert_read_http(&cert, p, res); |
| 1636 | if (APR_SUCCESS != rv) goto cleanup; |
| 1637 | APR_ARRAY_PUSH(chain, md_cert_t *) = cert; |
| 1638 | } |
| 1639 | else if (!strcmp("application/pem-certificate-chain", ct) |
| 1640 | || !strncmp("text/plain", ct, sizeof("text/plain")-1)) { |
| 1641 | /* Some servers seem to think 'text/plain' is sufficient, see #232 */ |
| 1642 | rv = apr_brigade_pflatten(res->body, &data, &data_len, res->req->pool); |
| 1643 | if (APR_SUCCESS != rv) goto cleanup; |
| 1644 | rv = md_cert_read_chain(chain, res->req->pool, data, data_len); |
| 1645 | } |
| 1646 | else { |
| 1647 | md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p, |
| 1648 | "attempting to parse certificates from unrecognized content-type: %s", ct); |
| 1649 | rv = apr_brigade_pflatten(res->body, &data, &data_len, res->req->pool); |
| 1650 | if (APR_SUCCESS != rv) goto cleanup; |
| 1651 | rv = md_cert_read_chain(chain, res->req->pool, data, data_len); |
| 1652 | if (APR_SUCCESS == rv && chain->nelts == 0) { |
| 1653 | md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, |
| 1654 | "certificate chain response did not contain any certificates " |
| 1655 | "(suspicious content-type: %s)", ct); |
| 1656 | rv = APR_ENOENT; |
| 1657 | } |
| 1658 | } |
| 1659 | cleanup: |
| 1660 | md_log_perror(MD_LOG_MARK, MD_LOG_TRACE2, rv, p, |
| 1661 | "parsed certs from content-type=%s, content-length=%ld", ct, (long)data_len); |
| 1662 | return rv; |
| 1663 | } |
| 1664 | |
| 1665 | md_cert_state_t md_cert_state_get(const md_cert_t *cert) |
| 1666 | { |
no test coverage detected