Accidently I mailed an unfinished version of the patch. Attached is the
correct version, that seems to run on my system.
Regards,
Matthias
--
Matthias Wimmer USt-IdNr. DE244176643
Contact details: http://matthias.wimmer.tel/
Description: <short summary of the patch>
TODO: Put a short summary on the line above and replace this paragraph
with a longer explanation of this change. Complete the meta-information
with other relevant fields (see below for details). To make it easier, the
information below has been extracted from the changelog. Adjust it or drop
it.
.
mod-gnutls (0.5.10-1.1) unstable; urgency=low
.
[ Bastiaan Franciscus van den Dikkenberg ]
* Non-maintainer upload.
* Fix "default-tls file for apache" Added default-tls file
(Closes: #558232)
* Fix "configure: *** memcache library not found."
added build-depensie to libapr-memcache-dev (Closes: #497097)
* apache2-dev is releplaced by apache2-threaded-dev (Closes: #667626)
* DEP-5 url changed in copyright file to new standard
Author: Bastiaan Franciscus van den Dikkenberg <[email protected]>
Bug-Debian: http://bugs.debian.org/497097
Bug-Debian: http://bugs.debian.org/558232
Bug-Debian: http://bugs.debian.org/667626
---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:
Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>
--- mod-gnutls-0.5.10.orig/src/gnutls_hooks.c
+++ mod-gnutls-0.5.10/src/gnutls_hooks.c
@@ -243,75 +243,104 @@ const char static_dh_params[] = "-----BE
* Returns negative on error.
*/
static int read_crt_cn(server_rec * s, apr_pool_t * p,
- gnutls_x509_crt_t cert, char **cert_cn)
+ gnutls_x509_crt_t cert, char ***cert_cn)
{
int rv = 0, i;
size_t data_len;
+ size_t buffer_len;
+ int number_names;
+ int copied_names;
+ char *buffer;
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
- *cert_cn = NULL;
- data_len = 0;
+ // find number of alt names
+ number_names = 0;
+ buffer_len = 0;
+ buffer = NULL;
+ do {
+ data_len = buffer_len;
+ rv = gnutls_x509_crt_get_subject_alt_name(cert, number_names, buffer, &data_len, NULL);
+
+ // the first buffer we allocate, or we need bigger buffer
+ if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
+ // be prepared for longer names coming later without need to reallocate memory
+ buffer_len = data_len * 2;
+ buffer = apr_palloc(p, buffer_len);
+
+ data_len = buffer_len;
+ rv = gnutls_x509_crt_get_subject_alt_name(cert, number_names, buffer, &data_len, NULL);
+ }
+
+ // one more name available, the last one we count is a fail we can use to store the CN
+ number_names++;
+ } while (rv >= 0);
+
+ // allocate memory of the list of names, plus one for the terminating NULL
+ *cert_cn = apr_palloc(p, sizeof(char*) * (number_names + 2));
+
+ // first name we try to get is CN
+ copied_names = 0;
+ data_len = buffer_len;
rv = gnutls_x509_crt_get_dn_by_oid(cert,
GNUTLS_OID_X520_COMMON_NAME,
- 0, 0, NULL, &data_len);
+ 0, 0, buffer, &data_len);
if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
- *cert_cn = apr_palloc(p, data_len);
+ buffer_len = data_len;
+ buffer = apr_palloc(p, buffer_len);
rv = gnutls_x509_crt_get_dn_by_oid(cert,
GNUTLS_OID_X520_COMMON_NAME,
- 0, 0, *cert_cn,
+ 0, 0, buffer,
&data_len);
- } else { /* No CN return subject alternative name */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
- "No common name found in certificate for '%s:%d'. Looking for subject alternative name...",
- s->server_hostname, s->port);
- rv = 0;
- /* read subject alternative name */
- for (i = 0; !(rv < 0); i++) {
- data_len = 0;
- rv = gnutls_x509_crt_get_subject_alt_name(cert, i,
- NULL,
- &data_len,
- NULL);
-
- if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER
- && data_len > 1) {
- /* FIXME: not very efficient. What if we have several alt names
- * before DNSName?
- */
- *cert_cn = apr_palloc(p, data_len + 1);
-
- rv = gnutls_x509_crt_get_subject_alt_name
- (cert, i, *cert_cn, &data_len, NULL);
- (*cert_cn)[data_len] = 0;
+ }
- if (rv == GNUTLS_SAN_DNSNAME)
- break;
- }
+ if (rv >= 0) {
+ (*cert_cn)[0] = apr_palloc(p, data_len + 1);
+ apr_cpystrn((*cert_cn)[0], buffer, data_len + 1);
+ copied_names++;
+ }
+
+ // now we have to find subject alternative names
+ for (i = 0; i < number_names - 1 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER; i++) {
+ data_len = buffer_len;
+ rv = gnutls_x509_crt_get_subject_alt_name(cert, i, buffer, &data_len, NULL);
+
+ // we only ever increased buffer size, should get no memory problem anymore
+
+ // on success, copy result in the list
+ if (rv == GNUTLS_SAN_DNSNAME) {
+ (*cert_cn)[copied_names] = apr_palloc(p, data_len + 1);
+ apr_cpystrn((*cert_cn)[copied_names], buffer, data_len + 1);
+ copied_names++;
}
}
- return rv;
+ // terminate list
+ (*cert_cn)[copied_names + 1] = NULL;
+
+ return copied_names >= 1 ? 0 : -1;
}
static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p,
- gnutls_openpgp_crt_t cert, char **cert_cn)
+ gnutls_openpgp_crt_t cert, char ***cert_cn)
{
int rv = 0;
size_t data_len;
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
- *cert_cn = NULL;
+ *cert_cn = apr_palloc(p, sizeof(char*) * 2);
+ (*cert_cn)[0] = NULL;
+ (*cert_cn)[1] = NULL;
data_len = 0;
rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len);
if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
- *cert_cn = apr_palloc(p, data_len);
- rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn,
+ (*cert_cn)[0] = apr_palloc(p, data_len);
+ rv = gnutls_openpgp_crt_get_name(cert, 0, (*cert_cn)[0],
&data_len);
} else { /* No CN return subject alternative name */
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
@@ -558,6 +587,7 @@ typedef struct {
static int vhost_cb(void *baton, conn_rec * conn, server_rec * s)
{
+ int tried_name = 0;
mgs_srvconf_rec *tsc;
vhost_cb_rec *x = baton;
@@ -569,31 +599,35 @@ static int vhost_cb(void *baton, conn_re
return 0;
}
- /* The CN can contain a * -- this will match those too. */
- if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) {
- /* found a match */
+ /* try all names of the host */
+ for (tried_name = 0; tsc->cert_cn[tried_name] != NULL; tried_name++) {
+
+ /* The CN can contain a * -- this will match those too. */
+ if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn[tried_name]) == 0) {
+ /* found a match */
#if MOD_GNUTLS_DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- x->ctxt->c->base_server,
- "GnuTLS: Virtual Host CB: "
- "'%s' == '%s'", tsc->cert_cn, x->sni_name);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
+ x->ctxt->c->base_server,
+ "GnuTLS: Virtual Host CB: "
+ "'%s' == '%s'", tsc->cert_cn[tried_name], x->sni_name);
#endif
- /* Because we actually change the server used here, we need to reset
- * things like ClientVerify.
- */
- x->sc = tsc;
- /* Shit. Crap. Dammit. We *really* should rehandshake here, as our
- * certificate structure *should* change when the server changes.
- * acccckkkkkk.
- */
- return 1;
- } else {
+ /* Because we actually change the server used here, we need to reset
+ * things like ClientVerify.
+ */
+ x->sc = tsc;
+ /* Shit. Crap. Dammit. We *really* should rehandshake here, as our
+ * certificate structure *should* change when the server changes.
+ * acccckkkkkk.
+ */
+ return 1;
+ } else {
#if MOD_GNUTLS_DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- x->ctxt->c->base_server,
- "GnuTLS: Virtual Host CB: "
- "'%s' != '%s'", tsc->cert_cn, x->sni_name);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
+ x->ctxt->c->base_server,
+ "GnuTLS: Virtual Host CB: "
+ "'%s' != '%s'", tsc->cert_cn[tried_name], x->sni_name);
#endif
+ }
}
return 0;
@@ -602,6 +636,7 @@ static int vhost_cb(void *baton, conn_re
mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
{
+ int i;
int rv;
unsigned int sni_type;
size_t data_len = MAX_HOST_LEN;
@@ -661,22 +696,24 @@ mgs_srvconf_rec *mgs_find_sni_server(gnu
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
ctxt->c->base_server,
"GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X",
- tsc->cert_cn, rv,
+ tsc->cert_cn[0], rv,
gnutls_pk_algorithm_get_name
(gnutls_x509_privkey_get_pk_algorithm
(ctxt->sc->privkey_x509)), (unsigned int) s,
(unsigned int) s->next, (unsigned int) tsc);
#endif
/* The CN can contain a * -- this will match those too. */
- if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) {
+ for (i = 0; tsc->cert_cn[i] != NULL; i++) [
+ if (ap_strcasecmp_match(sni_name, tsc->cert_cn[i]) == 0) {
#if MOD_GNUTLS_DEBUG
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- ctxt->c->base_server,
- "GnuTLS: Virtual Host: "
- "'%s' == '%s'", tsc->cert_cn,
- sni_name);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
+ ctxt->c->base_server,
+ "GnuTLS: Virtual Host: "
+ "'%s' == '%s'", tsc->cert_cn[i],
+ sni_name);
#endif
- return tsc;
+ return tsc;
+ }
}
}
#endif
--- mod-gnutls-0.5.10.orig/include/mod_gnutls.h.in
+++ mod-gnutls-0.5.10/include/mod_gnutls.h.in
@@ -86,7 +86,7 @@ typedef struct
gnutls_certificate_credentials_t certs;
gnutls_srp_server_credentials_t srp_creds;
gnutls_anon_server_credentials_t anon_creds;
- char* cert_cn;
+ char** cert_cn;
gnutls_x509_crt_t certs_x509[MAX_CHAIN_SIZE]; /* A certificate chain */
unsigned int certs_x509_num;
gnutls_x509_privkey_t privkey_x509;