1c41633f0b
Copy from GNOME:Factory/libesmtp based on submit request 39315 from user dimstar OBS-URL: https://build.opensuse.org/request/show/39315 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libesmtp?expand=0&rev=6
174 lines
4.8 KiB
Diff
174 lines
4.8 KiB
Diff
--- smtp-tls.c.orig 2005-12-15 18:59:49.000000000 +0000
|
|
+++ smtp-tls.c 2010-03-17 01:15:06.000000000 +0000
|
|
@@ -439,15 +439,32 @@
|
|
match_component (const char *dom, const char *edom,
|
|
const char *ref, const char *eref)
|
|
{
|
|
- while (dom < edom && ref < eref)
|
|
+ /* If ref is the single character '*' then accept this as a wildcard
|
|
+ matching any valid domainname component, i.e. characters from the
|
|
+ range A-Z, a-z, 0-9, - or _
|
|
+ NB this is more restrictive than RFC 2818 which allows multiple
|
|
+ wildcard characters in the component pattern */
|
|
+ if (eref == ref + 1 && *ref == '*')
|
|
+ while (dom < edom)
|
|
+ {
|
|
+ if (!(isalnum (*dom) || *dom == '-' /*|| *dom == '_'*/))
|
|
+ return 0;
|
|
+ dom++;
|
|
+ }
|
|
+ else
|
|
{
|
|
- /* Accept a final '*' in the reference as a wildcard */
|
|
- if (*ref == '*' && ref + 1 == eref)
|
|
- break;
|
|
- /* compare the domain name case insensitive */
|
|
- if (!(*dom == *ref || tolower (*dom) == tolower (*ref)))
|
|
- return 0;
|
|
- ref++, dom++;
|
|
+ while (dom < edom && ref < eref)
|
|
+ {
|
|
+ /* check for valid domainname character */
|
|
+ if (!(isalnum (*dom) || *dom == '-' /*|| *dom == '_'*/))
|
|
+ return 0;
|
|
+ /* compare the domain name case-insensitively */
|
|
+ if (!(*dom == *ref || tolower (*dom) == tolower (*ref)))
|
|
+ return 0;
|
|
+ ref++, dom++;
|
|
+ }
|
|
+ if (dom < edom || ref < eref)
|
|
+ return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
@@ -541,65 +560,83 @@
|
|
}
|
|
else
|
|
{
|
|
- int i, j, extcount;
|
|
+ char buf[256] = { 0 };
|
|
+ STACK_OF(GENERAL_NAME) *altnames;
|
|
+ int hasaltname = 0;
|
|
|
|
- extcount = X509_get_ext_count (cert);
|
|
- for (i = 0; i < extcount; i++)
|
|
+ altnames = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
|
|
+ if (altnames != NULL)
|
|
{
|
|
- const char *extstr;
|
|
- X509_EXTENSION *ext = X509_get_ext (cert, i);
|
|
+ int i;
|
|
|
|
- extstr = OBJ_nid2sn (OBJ_obj2nid (X509_EXTENSION_get_object (ext)));
|
|
- if (strcmp (extstr, "subjectAltName") == 0)
|
|
+ for (i = 0; i < sk_GENERAL_NAME_num (altnames); ++i)
|
|
{
|
|
- unsigned char *data;
|
|
- STACK_OF(CONF_VALUE) *val;
|
|
- CONF_VALUE *nval;
|
|
- X509V3_EXT_METHOD *meth;
|
|
- void *ext_str = NULL;
|
|
- int stack_len;
|
|
-
|
|
- meth = X509V3_EXT_get (ext);
|
|
- if (meth == NULL)
|
|
- break;
|
|
- data = ext->value->data;
|
|
-#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
|
|
- if (meth->it)
|
|
- ext_str = ASN1_item_d2i (NULL, &data, ext->value->length,
|
|
- ASN1_ITEM_ptr (meth->it));
|
|
- else
|
|
-#endif
|
|
- ext_str = meth->d2i (NULL, &data, ext->value->length);
|
|
- val = meth->i2v (meth, ext_str, NULL);
|
|
- stack_len = sk_CONF_VALUE_num (val);
|
|
- for (j = 0; j < stack_len; j++)
|
|
+ GENERAL_NAME *name = sk_GENERAL_NAME_value (altnames, i);
|
|
+
|
|
+ if (name->type == GEN_DNS)
|
|
{
|
|
- nval = sk_CONF_VALUE_value (val, j);
|
|
- if (strcmp (nval->name, "DNS") == 0
|
|
- && match_domain (session->host, nval->value))
|
|
+ const char *ia5str = (const char *) name->d.ia5->data;
|
|
+ int ia5len = name->d.ia5->length;
|
|
+
|
|
+ hasaltname = 1;
|
|
+ if (strlen (ia5str) == ia5len
|
|
+ && match_domain (session->host, ia5str))
|
|
+ ok = 1;
|
|
+ else
|
|
{
|
|
- ok = 1;
|
|
- break;
|
|
+ buf[0] = '\0';
|
|
+ strncat (buf, ia5str, sizeof buf - 1);
|
|
}
|
|
}
|
|
+ // TODO: handle GEN_IPADD
|
|
}
|
|
- if (ok)
|
|
- break;
|
|
+ sk_GENERAL_NAME_pop_free (altnames, GENERAL_NAME_free);
|
|
}
|
|
- if (!ok)
|
|
+
|
|
+ if (!hasaltname)
|
|
{
|
|
- /* Matching by subjectAltName failed, try commonName */
|
|
- X509_NAME_get_text_by_NID (X509_get_subject_name (cert),
|
|
- NID_commonName, buf, sizeof buf);
|
|
- if (!match_domain (session->host, buf) != 0)
|
|
+ X509_NAME *subj = X509_get_subject_name (cert);
|
|
+
|
|
+ if (subj != NULL)
|
|
{
|
|
- if (session->event_cb != NULL)
|
|
- (*session->event_cb) (session, SMTP_EV_WRONG_PEER_CERTIFICATE,
|
|
- session->event_cb_arg, &ok, buf, ssl);
|
|
+ ASN1_STRING *cn;
|
|
+ int idx, i = -1;
|
|
+
|
|
+ do
|
|
+ {
|
|
+ idx = i;
|
|
+ i = X509_NAME_get_index_by_NID (subj, NID_commonName, i);
|
|
+ }
|
|
+ while (i >= 0);
|
|
+
|
|
+ if (idx >= 0
|
|
+ && (cn = X509_NAME_ENTRY_get_data (
|
|
+ X509_NAME_get_entry (subj, idx)
|
|
+ )) != NULL)
|
|
+ {
|
|
+ unsigned char *str = NULL;
|
|
+ int len = ASN1_STRING_to_UTF8 (&str, cn);
|
|
+
|
|
+ if (str != NULL)
|
|
+ {
|
|
+ if (strlen ((char *) str) == len
|
|
+ && match_domain (session->host, (char *) str))
|
|
+ ok = 1;
|
|
+ else
|
|
+ {
|
|
+ buf[0] = '\0';
|
|
+ strncat (buf, (char *) str, sizeof buf - 1);
|
|
+ }
|
|
+ OPENSSL_free (str);
|
|
+ }
|
|
+ }
|
|
}
|
|
- else
|
|
- ok = 1;
|
|
}
|
|
+
|
|
+ if (!ok && session->event_cb != NULL)
|
|
+ (*session->event_cb) (session, SMTP_EV_WRONG_PEER_CERTIFICATE,
|
|
+ session->event_cb_arg, &ok, buf, ssl);
|
|
+
|
|
X509_free (cert);
|
|
}
|
|
return ok;
|
|
|