On Thu, Jun 18, 2015 at 12:22:21PM +0200, Yann Ylavic wrote:
> On Thu, Jun 18, 2015 at 11:49 AM, Jan Pazdziora <[email protected]> wrote:
> >
> > I'd appreciate any comments about suitability of such change, as well
> > as the implementation. Specifically, I'm not sure if people will
> > prefer the generic and currently proposed
> >
> > SSL_CLIENT_SAN_otherName_n
> >
> > which gets any value of otherName type, or perhaps going with
> >
> > SSL_CLIENT_SAN_UPN_n
> >
> > and checking the OID just for the UPNs. Based on that decision I plan
> > to then respin the patch with documentation changes included.
>
> I think a more generic way would to have something like
> SSL_CLIENT_OID_<oid>_n, so that we wouldn't have to add a new field
> each time.
> In this case, that would be: SSL_CLIENT_OID_1.3.6.1.4.1.311.20.2.3_n.
Please find attached a patch which makes it possible to use
SSL_CLIENT_SAN_otherName_1.3.6.1.4.1.311.20.2.3_0
or
SSL_CLIENT_SAN_otherName_0
In the first case we use OBJ_create to create the object and then
compare its nid to OBJ_obj2nid result. In the second form we ignore
the OID.
I went with the SAN_otherName rather than OID to make it clear where
we get the value from. Of course, of you think that
SSL_CLIENT_OID_1.3.6.1.4.1.311.20.2.3_n better and the correct place
to look for it is always in name->d.otherName, it should be easy to
change the name.
--
Jan Pazdziora
Senior Principal Software Engineer, Identity Management Engineering, Red Hat
Index: modules/ssl/ssl_engine_vars.c
===================================================================
--- modules/ssl/ssl_engine_vars.c (revision 1686420)
+++ modules/ssl/ssl_engine_vars.c (working copy)
@@ -663,8 +663,9 @@
static char *ssl_var_lookup_ssl_cert_san(apr_pool_t *p, X509 *xs, char *var)
{
- int type, numlen;
+ int type, numlen, nid = NID_undef;
apr_array_header_t *entries;
+ char *ptr;
if (strcEQn(var, "Email_", 6)) {
type = GEN_EMAIL;
@@ -674,6 +675,17 @@
type = GEN_DNS;
var += 4;
}
+ else if (strcEQn(var, "otherName_", 10)) {
+ type = GEN_OTHERNAME;
+ var += 10;
+ ptr = strchr(var, '_');
+ if (ptr) {
+ char *oid_str;
+ oid_str = apr_pstrndup(p, var, (ptr - var));
+ nid = OBJ_create(oid_str, NULL, NULL);
+ var = ptr + 1;
+ }
+ }
else
return NULL;
@@ -682,7 +694,7 @@
if ((numlen < 1) || (numlen > 4) || (numlen != strlen(var)))
return NULL;
- if (modssl_X509_getSAN(p, xs, type, atoi(var), &entries))
+ if (modssl_X509_getSAN(p, xs, type, nid, atoi(var), &entries))
/* return the first entry from this 1-element array */
return APR_ARRAY_IDX(entries, 0, char *);
else
@@ -1032,10 +1044,10 @@
/* subjectAltName entries of the server certificate */
xs = SSL_get_certificate(ssl);
if (xs) {
- if (modssl_X509_getSAN(p, xs, GEN_EMAIL, -1, &entries)) {
+ if (modssl_X509_getSAN(p, xs, GEN_EMAIL, NID_undef, -1, &entries)) {
extract_san_array(t, "SSL_SERVER_SAN_Email", entries, p);
}
- if (modssl_X509_getSAN(p, xs, GEN_DNS, -1, &entries)) {
+ if (modssl_X509_getSAN(p, xs, GEN_DNS, NID_undef, -1, &entries)) {
extract_san_array(t, "SSL_SERVER_SAN_DNS", entries, p);
}
/* no need to free xs (refcount does not increase) */
@@ -1044,10 +1056,10 @@
/* subjectAltName entries of the client certificate */
xs = SSL_get_peer_certificate(ssl);
if (xs) {
- if (modssl_X509_getSAN(p, xs, GEN_EMAIL, -1, &entries)) {
+ if (modssl_X509_getSAN(p, xs, GEN_EMAIL, NID_undef, -1, &entries)) {
extract_san_array(t, "SSL_CLIENT_SAN_Email", entries, p);
}
- if (modssl_X509_getSAN(p, xs, GEN_DNS, -1, &entries)) {
+ if (modssl_X509_getSAN(p, xs, GEN_DNS, NID_undef, -1, &entries)) {
extract_san_array(t, "SSL_CLIENT_SAN_DNS", entries, p);
}
X509_free(xs);
Index: modules/ssl/ssl_util_ssl.c
===================================================================
--- modules/ssl/ssl_util_ssl.c (revision 1686420)
+++ modules/ssl/ssl_util_ssl.c (working copy)
@@ -258,8 +258,9 @@
* of the n-th occurrence of that type only. Currently supported types:
* GEN_EMAIL (rfc822Name)
* GEN_DNS (dNSName)
+ * GEN_OTHERNAME (otherName)
*/
-BOOL modssl_X509_getSAN(apr_pool_t *p, X509 *x509, int type, int idx,
+BOOL modssl_X509_getSAN(apr_pool_t *p, X509 *x509, int type, int nid, int idx,
apr_array_header_t **entries)
{
STACK_OF(GENERAL_NAME) *names;
@@ -287,10 +288,19 @@
APR_ARRAY_PUSH(*entries, const char *) = utf8str;
}
break;
+ case GEN_OTHERNAME:
+ if (name->d.otherName && name->d.otherName->value
+ && (nid == NID_undef
+ || nid ==
OBJ_obj2nid(name->d.otherName->type_id))) {
+ utf8str = asn1_string_to_utf8(p,
name->d.otherName->value->value.asn1_string);
+ if (utf8str) {
+ APR_ARRAY_PUSH(*entries, const char *) =
utf8str;
+ }
+ }
+ break;
default:
/*
* Not implemented right now:
- * GEN_OTHERNAME (otherName)
* GEN_X400 (x400Address)
* GEN_DIRNAME (directoryName)
* GEN_EDIPARTY (ediPartyName)
@@ -320,7 +330,7 @@
/* First, the DNS-IDs (dNSName entries in the subjectAltName extension) */
if (!x509 ||
- (modssl_X509_getSAN(p, x509, GEN_DNS, -1, ids) == FALSE && !*ids)) {
+ (modssl_X509_getSAN(p, x509, GEN_DNS, NID_undef, -1, ids) == FALSE &&
!*ids)) {
*ids = NULL;
return FALSE;
}
Index: modules/ssl/ssl_util_ssl.h
===================================================================
--- modules/ssl/ssl_util_ssl.h (revision 1686420)
+++ modules/ssl/ssl_util_ssl.h (working copy)
@@ -65,7 +65,7 @@
BOOL modssl_X509_getBC(X509 *, int *, int *);
char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY
*xsne);
char *modssl_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int);
-BOOL modssl_X509_getSAN(apr_pool_t *, X509 *, int, int,
apr_array_header_t **);
+BOOL modssl_X509_getSAN(apr_pool_t *, X509 *, int, int, int,
apr_array_header_t **);
BOOL modssl_X509_match_name(apr_pool_t *, X509 *, const char *, BOOL,
server_rec *);
char *modssl_SSL_SESSION_id2sz(unsigned char *, int, char *, int);