Import serf-1.3.7
This commit is contained in:
parent
b42ed20721
commit
b907131b5f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/serf/dist/; revision=269831 svn path=/vendor/serf/serf-1.3.7/; revision=269832; tag=vendor/serf/serf-1.3.7
7
CHANGES
7
CHANGES
@ -1,8 +1,11 @@
|
|||||||
Serf 1.3.6 [2014-06-09, from /tags/1.3.6, rxxxx]
|
Serf 1.3.7 [2014-08-11, from /tags/1.3.7, r2411]
|
||||||
|
Handle NUL bytes in fields of an X.509 certificate. (r2393, r2399)
|
||||||
|
|
||||||
|
Serf 1.3.6 [2014-06-09, from /tags/1.3.6, r2372]
|
||||||
Revert r2319 from serf 1.3.5: this change was making serf call handle_response
|
Revert r2319 from serf 1.3.5: this change was making serf call handle_response
|
||||||
multiple times in case of an error response, leading to unexpected behavior.
|
multiple times in case of an error response, leading to unexpected behavior.
|
||||||
|
|
||||||
Serf 1.3.5 [2014-04-27, from /tags/1.3.5, rxxxx]
|
Serf 1.3.5 [2014-04-27, from /tags/1.3.5, r2355]
|
||||||
Fix issue #125: no reverse lookup during Negotiate authentication for proxies.
|
Fix issue #125: no reverse lookup during Negotiate authentication for proxies.
|
||||||
Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)
|
Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)
|
||||||
Cancel request if response parsing failed + authn callback set (r2319)
|
Cancel request if response parsing failed + authn callback set (r2319)
|
||||||
|
@ -202,6 +202,8 @@ struct serf_ssl_certificate_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void disable_compression(serf_ssl_context_t *ssl_ctx);
|
static void disable_compression(serf_ssl_context_t *ssl_ctx);
|
||||||
|
static char *
|
||||||
|
pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool);
|
||||||
|
|
||||||
#if SSL_VERBOSE
|
#if SSL_VERBOSE
|
||||||
/* Log all ssl alerts that we receive from the server. */
|
/* Log all ssl alerts that we receive from the server. */
|
||||||
@ -427,6 +429,85 @@ static BIO_METHOD bio_file_method = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum san_copy_t {
|
||||||
|
EscapeNulAndCopy = 0,
|
||||||
|
ErrorOnNul = 1,
|
||||||
|
} san_copy_t;
|
||||||
|
|
||||||
|
|
||||||
|
static apr_status_t
|
||||||
|
get_subject_alt_names(apr_array_header_t **san_arr, X509 *ssl_cert,
|
||||||
|
san_copy_t copy_action, apr_pool_t *pool)
|
||||||
|
{
|
||||||
|
STACK_OF(GENERAL_NAME) *names;
|
||||||
|
|
||||||
|
/* assert: copy_action == ErrorOnNul || (san_arr && pool) */
|
||||||
|
|
||||||
|
if (san_arr) {
|
||||||
|
*san_arr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get subjectAltNames */
|
||||||
|
names = X509_get_ext_d2i(ssl_cert, NID_subject_alt_name, NULL, NULL);
|
||||||
|
if (names) {
|
||||||
|
int names_count = sk_GENERAL_NAME_num(names);
|
||||||
|
int name_idx;
|
||||||
|
|
||||||
|
if (san_arr)
|
||||||
|
*san_arr = apr_array_make(pool, names_count, sizeof(char*));
|
||||||
|
for (name_idx = 0; name_idx < names_count; name_idx++) {
|
||||||
|
char *p = NULL;
|
||||||
|
GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, name_idx);
|
||||||
|
|
||||||
|
switch (nm->type) {
|
||||||
|
case GEN_DNS:
|
||||||
|
if (copy_action == ErrorOnNul &&
|
||||||
|
strlen(nm->d.ia5->data) != nm->d.ia5->length)
|
||||||
|
return SERF_ERROR_SSL_CERT_FAILED;
|
||||||
|
if (san_arr && *san_arr)
|
||||||
|
p = pstrdup_escape_nul_bytes((const char *)nm->d.ia5->data,
|
||||||
|
nm->d.ia5->length,
|
||||||
|
pool);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Don't know what to do - skip. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
APR_ARRAY_PUSH(*san_arr, char*) = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
return APR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static apr_status_t validate_cert_hostname(X509 *server_cert, apr_pool_t *pool)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
int length;
|
||||||
|
apr_status_t ret;
|
||||||
|
|
||||||
|
ret = get_subject_alt_names(NULL, server_cert, ErrorOnNul, NULL);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
/* Fail if the subject's CN field contains \0 characters. */
|
||||||
|
X509_NAME *subject = X509_get_subject_name(server_cert);
|
||||||
|
if (!subject)
|
||||||
|
return SERF_ERROR_SSL_CERT_FAILED;
|
||||||
|
|
||||||
|
length = X509_NAME_get_text_by_NID(subject, NID_commonName, buf, 1024);
|
||||||
|
if (length != -1)
|
||||||
|
if (strlen(buf) != length)
|
||||||
|
return SERF_ERROR_SSL_CERT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return APR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
||||||
{
|
{
|
||||||
@ -435,6 +516,7 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
|||||||
X509 *server_cert;
|
X509 *server_cert;
|
||||||
int err, depth;
|
int err, depth;
|
||||||
int failures = 0;
|
int failures = 0;
|
||||||
|
apr_status_t status;
|
||||||
|
|
||||||
ssl = X509_STORE_CTX_get_ex_data(store_ctx,
|
ssl = X509_STORE_CTX_get_ex_data(store_ctx,
|
||||||
SSL_get_ex_data_X509_STORE_CTX_idx());
|
SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||||
@ -475,6 +557,11 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate hostname */
|
||||||
|
status = validate_cert_hostname(server_cert, ctx->pool);
|
||||||
|
if (status)
|
||||||
|
failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
|
||||||
|
|
||||||
/* Check certificate expiry dates. */
|
/* Check certificate expiry dates. */
|
||||||
if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
|
if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
|
||||||
failures |= SERF_SSL_CERT_NOTYETVALID;
|
failures |= SERF_SSL_CERT_NOTYETVALID;
|
||||||
@ -485,7 +572,6 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
|||||||
|
|
||||||
if (ctx->server_cert_callback &&
|
if (ctx->server_cert_callback &&
|
||||||
(depth == 0 || failures)) {
|
(depth == 0 || failures)) {
|
||||||
apr_status_t status;
|
|
||||||
serf_ssl_certificate_t *cert;
|
serf_ssl_certificate_t *cert;
|
||||||
apr_pool_t *subpool;
|
apr_pool_t *subpool;
|
||||||
|
|
||||||
@ -512,7 +598,6 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
|||||||
|
|
||||||
if (ctx->server_cert_chain_callback
|
if (ctx->server_cert_chain_callback
|
||||||
&& (depth == 0 || failures)) {
|
&& (depth == 0 || failures)) {
|
||||||
apr_status_t status;
|
|
||||||
STACK_OF(X509) *chain;
|
STACK_OF(X509) *chain;
|
||||||
const serf_ssl_certificate_t **certs;
|
const serf_ssl_certificate_t **certs;
|
||||||
int certs_len;
|
int certs_len;
|
||||||
@ -1461,7 +1546,50 @@ serf_ssl_context_t *serf_bucket_ssl_encrypt_context_get(
|
|||||||
|
|
||||||
/* Functions to read a serf_ssl_certificate structure. */
|
/* Functions to read a serf_ssl_certificate structure. */
|
||||||
|
|
||||||
/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
|
/* Takes a counted length string and escapes any NUL bytes so that
|
||||||
|
* it can be used as a C string. NUL bytes are escaped as 3 characters
|
||||||
|
* "\00" (that's a literal backslash).
|
||||||
|
* The returned string is allocated in POOL.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool)
|
||||||
|
{
|
||||||
|
int i, nul_count = 0;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
/* First determine if there are any nul bytes in the string. */
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (buf[i] == '\0')
|
||||||
|
nul_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nul_count == 0) {
|
||||||
|
/* There aren't so easy case to just copy the string */
|
||||||
|
ret = apr_pstrdup(pool, buf);
|
||||||
|
} else {
|
||||||
|
/* There are so we have to replace nul bytes with escape codes
|
||||||
|
* Proper length is the length of the original string, plus
|
||||||
|
* 2 times the number of nulls (for two digit hex code for
|
||||||
|
* the value) + the trailing null. */
|
||||||
|
char *pos;
|
||||||
|
ret = pos = apr_palloc(pool, len + 2 * nul_count + 1);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (buf[i] != '\0') {
|
||||||
|
*(pos++) = buf[i];
|
||||||
|
} else {
|
||||||
|
*(pos++) = '\\';
|
||||||
|
*(pos++) = '0';
|
||||||
|
*(pos++) = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pos = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). Any NUL bytes in
|
||||||
|
these fields in the certificate will be escaped as \00. */
|
||||||
static apr_hash_t *
|
static apr_hash_t *
|
||||||
convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
|
convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
|
||||||
{
|
{
|
||||||
@ -1474,37 +1602,44 @@ convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
|
|||||||
NID_commonName,
|
NID_commonName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_pkcs9_emailAddress,
|
NID_pkcs9_emailAddress,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "E", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_organizationalUnitName,
|
NID_organizationalUnitName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_organizationName,
|
NID_organizationName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "O", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_localityName,
|
NID_localityName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "L", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_stateOrProvinceName,
|
NID_stateOrProvinceName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
ret = X509_NAME_get_text_by_NID(org,
|
ret = X509_NAME_get_text_by_NID(org,
|
||||||
NID_countryName,
|
NID_countryName,
|
||||||
buf, 1024);
|
buf, 1024);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
|
apr_hash_set(tgt, "C", APR_HASH_KEY_STRING,
|
||||||
|
pstrdup_escape_nul_bytes(buf, ret, pool));
|
||||||
|
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
@ -1550,7 +1685,7 @@ apr_hash_t *serf_ssl_cert_certificate(
|
|||||||
unsigned int md_size, i;
|
unsigned int md_size, i;
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
STACK_OF(GENERAL_NAME) *names;
|
apr_array_header_t *san_arr;
|
||||||
|
|
||||||
/* sha1 fingerprint */
|
/* sha1 fingerprint */
|
||||||
if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
|
if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
|
||||||
@ -1595,32 +1730,8 @@ apr_hash_t *serf_ssl_cert_certificate(
|
|||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
|
|
||||||
/* Get subjectAltNames */
|
/* Get subjectAltNames */
|
||||||
names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
|
if (!get_subject_alt_names(&san_arr, cert->ssl_cert, EscapeNulAndCopy, pool))
|
||||||
if (names) {
|
|
||||||
int names_count = sk_GENERAL_NAME_num(names);
|
|
||||||
|
|
||||||
apr_array_header_t *san_arr = apr_array_make(pool, names_count,
|
|
||||||
sizeof(char*));
|
|
||||||
apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
|
apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
|
||||||
for (i = 0; i < names_count; i++) {
|
|
||||||
char *p = NULL;
|
|
||||||
GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
|
|
||||||
|
|
||||||
switch (nm->type) {
|
|
||||||
case GEN_DNS:
|
|
||||||
p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
|
|
||||||
nm->d.ia5->length);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Don't know what to do - skip. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (p) {
|
|
||||||
APR_ARRAY_PUSH(san_arr, char*) = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
2
serf.h
2
serf.h
@ -1062,7 +1062,7 @@ void serf_debug__bucket_alloc_check(
|
|||||||
/* Version info */
|
/* Version info */
|
||||||
#define SERF_MAJOR_VERSION 1
|
#define SERF_MAJOR_VERSION 1
|
||||||
#define SERF_MINOR_VERSION 3
|
#define SERF_MINOR_VERSION 3
|
||||||
#define SERF_PATCH_VERSION 6
|
#define SERF_PATCH_VERSION 7
|
||||||
|
|
||||||
/* Version number string */
|
/* Version number string */
|
||||||
#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
|
#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
|
||||||
|
Loading…
Reference in New Issue
Block a user