summaryrefslogtreecommitdiffstats
path: root/contrib/serf
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2014-08-12 01:40:11 +0000
committerpeter <peter@FreeBSD.org>2014-08-12 01:40:11 +0000
commit72d63a715ab3bb85109696154deb9b90d0495852 (patch)
treece225c894795f3e26aadf9170baf8fd0556c18d2 /contrib/serf
parentd307c6d3b7fc94a241aab28f56b9e92a10d98bee (diff)
downloadFreeBSD-src-72d63a715ab3bb85109696154deb9b90d0495852.zip
FreeBSD-src-72d63a715ab3bb85109696154deb9b90d0495852.tar.gz
MFC r266728,266731,266735,266736,268135,268960,269833
Update apr 1.4.8 -> 1.5.1 Update apr-util 1.5.2 -> 1.5.3 Update serf 1.3.4 -> 1.3.7 Update svnlite 1.8.8 -> 1.8.10 Deal with svnlite.1 manpage.
Diffstat (limited to 'contrib/serf')
-rw-r--r--contrib/serf/CHANGES16
-rw-r--r--contrib/serf/auth/auth_spnego.c3
-rw-r--r--contrib/serf/buckets/ssl_buckets.c183
-rw-r--r--contrib/serf/serf.h2
-rw-r--r--contrib/serf/ssltunnel.c9
5 files changed, 168 insertions, 45 deletions
diff --git a/contrib/serf/CHANGES b/contrib/serf/CHANGES
index e4e1c89..6d39b0c 100644
--- a/contrib/serf/CHANGES
+++ b/contrib/serf/CHANGES
@@ -1,4 +1,18 @@
-Serf 1.3.4 [2014-02-08, from /tags/1.3.4, 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
+ multiple times in case of an error response, leading to unexpected behavior.
+
+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 a crash caused by incorrect reuse of the ssltunnel CONNECT request (r2316)
+ Cancel request if response parsing failed + authn callback set (r2319)
+ Update the expired certificates in the test suite.
+
+
+Serf 1.3.4 [2014-02-08, from /tags/1.3.4, r2310]
Fix issue #119: Endless loop during ssl tunnel setup with Negotiate authn
Fix issue #123: Can't setup ssl tunnel which sends Connection close header
Fix a race condition when initializing OpenSSL from multiple threads (r2263)
diff --git a/contrib/serf/auth/auth_spnego.c b/contrib/serf/auth/auth_spnego.c
index c0ad27e..e55fad2 100644
--- a/contrib/serf/auth/auth_spnego.c
+++ b/contrib/serf/auth/auth_spnego.c
@@ -335,8 +335,7 @@ do_auth(peer_t peer,
&tmp, &tmp_len,
gss_info);
} else {
- char *proxy_host;
- apr_getnameinfo(&proxy_host, conn->ctx->proxy_address, 0);
+ char *proxy_host = conn->ctx->proxy_address->hostname;
status = gss_api_get_credentials(conn,
token, token_len, proxy_host,
&tmp, &tmp_len,
diff --git a/contrib/serf/buckets/ssl_buckets.c b/contrib/serf/buckets/ssl_buckets.c
index 1a27d3f..d2fe51d 100644
--- a/contrib/serf/buckets/ssl_buckets.c
+++ b/contrib/serf/buckets/ssl_buckets.c
@@ -202,6 +202,8 @@ struct serf_ssl_certificate_t {
};
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
/* Log all ssl alerts that we receive from the server. */
@@ -427,6 +429,85 @@ static BIO_METHOD bio_file_method = {
#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
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;
int err, depth;
int failures = 0;
+ apr_status_t status;
ssl = X509_STORE_CTX_get_ex_data(store_ctx,
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. */
if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
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 &&
(depth == 0 || failures)) {
- apr_status_t status;
serf_ssl_certificate_t *cert;
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
&& (depth == 0 || failures)) {
- apr_status_t status;
STACK_OF(X509) *chain;
const serf_ssl_certificate_t **certs;
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. */
-/* 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 *
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,
buf, 1024);
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,
NID_pkcs9_emailAddress,
buf, 1024);
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,
NID_organizationalUnitName,
buf, 1024);
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,
NID_organizationName,
buf, 1024);
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,
NID_localityName,
buf, 1024);
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,
NID_stateOrProvinceName,
buf, 1024);
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,
NID_countryName,
buf, 1024);
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;
}
@@ -1550,7 +1685,7 @@ apr_hash_t *serf_ssl_cert_certificate(
unsigned int md_size, i;
unsigned char md[EVP_MAX_MD_SIZE];
BIO *bio;
- STACK_OF(GENERAL_NAME) *names;
+ apr_array_header_t *san_arr;
/* sha1 fingerprint */
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);
/* Get subjectAltNames */
- names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
- if (names) {
- int names_count = sk_GENERAL_NAME_num(names);
-
- apr_array_header_t *san_arr = apr_array_make(pool, names_count,
- sizeof(char*));
+ if (!get_subject_alt_names(&san_arr, cert->ssl_cert, EscapeNulAndCopy, pool))
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;
}
diff --git a/contrib/serf/serf.h b/contrib/serf/serf.h
index c28703f..f6f34a7 100644
--- a/contrib/serf/serf.h
+++ b/contrib/serf/serf.h
@@ -1062,7 +1062,7 @@ void serf_debug__bucket_alloc_check(
/* Version info */
#define SERF_MAJOR_VERSION 1
#define SERF_MINOR_VERSION 3
-#define SERF_PATCH_VERSION 4
+#define SERF_PATCH_VERSION 7
/* Version number string */
#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
diff --git a/contrib/serf/ssltunnel.c b/contrib/serf/ssltunnel.c
index 28ca127..0ad04d6 100644
--- a/contrib/serf/ssltunnel.c
+++ b/contrib/serf/ssltunnel.c
@@ -70,12 +70,11 @@ static apr_status_t handle_response(serf_request_t *request,
req_ctx_t *ctx = handler_baton;
serf_connection_t *conn = request->conn;
- if (! response) {
- serf_connection_request_create(conn,
- setup_request,
- ctx);
+ /* CONNECT request was cancelled. Assuming that this is during connection
+ reset, we can safely discard the request as a new one will be created
+ when setting up the next connection. */
+ if (!response)
return APR_SUCCESS;
- }
status = serf_bucket_response_status(response, &sl);
if (SERF_BUCKET_READ_ERROR(status)) {
OpenPOWER on IntegriCloud