On Thu, Jun 18, 2015 at 12:22:21PM +0200, Yann Ylavic wrote: > On Thu, Jun 18, 2015 at 11:49 AM, Jan Pazdziora <jpazdzi...@redhat.com> 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);