On 01/07/2015 01:24 PM, [email protected] wrote: > Author: kbrand > Date: Wed Jan 7 12:24:48 2015 > New Revision: 1650047 > > URL: http://svn.apache.org/r1650047 > Log: > Add support for extracting subjectAltName entries of type > rfc822Name and dNSName into SSL_{CLIENT,SERVER}_SAN_{Email,DNS}_n > variables. > > * docs/manual/mod/mod_ssl.xml: add SSL_*_SAN_*_n entries to the > environment variables table > > * modules/ssl/ssl_engine_kernel.c: in ssl_hook_Fixup, add extraction > of subjectAltName entries for the "StdEnvVars" case > > * modules/ssl/ssl_engine_vars.c: add support for retrieving the > SSL_{CLIENT,SERVER}_SAN_{Email,DNS}_n variables, either with > individual on-demand lookup (ssl_var_lookup_ssl_cert_san), > or with full-list extraction to the environment ("StdEnvVars") > > * modules/ssl/ssl_private.h: add modssl_var_extract_san_entries prototype > > * modules/ssl/ssl_util_ssl.c: implement SSL_X509_getSAN and > SSL_ASN1_STRING_to_utf8 helper functions, with factoring out common > code from SSL_X509_getIDs and SSL_X509_NAME_ENTRY_to_string where > suitable. Limit SSL_X509_getSAN to the two most common subjectAltName > entry types appearing in user or server certificates (i.e., rfc822Name > and dNSName), for the time being. > > * modules/ssl/ssl_util_ssl.h: add SSL_ASN1_STRING_to_utf8 > and SSL_X509_getSAN prototypes > > Modified: > httpd/httpd/trunk/CHANGES > httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml > httpd/httpd/trunk/modules/ssl/ssl_engine_kernel.c > httpd/httpd/trunk/modules/ssl/ssl_engine_vars.c > httpd/httpd/trunk/modules/ssl/ssl_private.h > httpd/httpd/trunk/modules/ssl/ssl_util_ssl.c > httpd/httpd/trunk/modules/ssl/ssl_util_ssl.h >
> Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_vars.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_vars.c?rev=1650047&r1=1650046&r2=1650047&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/ssl/ssl_engine_vars.c (original) > +++ httpd/httpd/trunk/modules/ssl/ssl_engine_vars.c Wed Jan 7 12:24:48 2015 > @@ -237,51 +247,84 @@ char *SSL_X509_NAME_to_string(apr_pool_t > return result; > } > > -/* return an array of (RFC 6125 coined) DNS-IDs and CN-IDs in a certificate > */ > -BOOL SSL_X509_getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids) > +/* > + * Return an array of subjectAltName entries of type "type". If idx is -1, > + * return all entries of the given type, otherwise return an array consisting > + * of the n-th occurrence of that type only. Currently supported types: > + * GEN_EMAIL (rfc822Name) > + * GEN_DNS (dNSName) > + */ > +BOOL SSL_X509_getSAN(apr_pool_t *p, X509 *x509, int type, int idx, > + apr_array_header_t **entries) > { > STACK_OF(GENERAL_NAME) *names; > - BIO *bio; > - X509_NAME *subj; > - char **cpp; > - int i, n; > > - if (!x509 || !(*ids = apr_array_make(p, 0, sizeof(char *)))) { > - *ids = NULL; > + if (!x509 || (type < GEN_OTHERNAME) || (type > GEN_RID) || (idx < -1) || > + !(*entries = apr_array_make(p, 0, sizeof(char *)))) { > + *entries = NULL; > return FALSE; > } > > - /* First, the DNS-IDs (dNSName entries in the subjectAltName extension) > */ > - if ((names = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)) && > - (bio = BIO_new(BIO_s_mem()))) { > + if ((names = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL))) { > + int i, n = 0; > GENERAL_NAME *name; > + const char *utf8str; > > for (i = 0; i < sk_GENERAL_NAME_num(names); i++) { > name = sk_GENERAL_NAME_value(names, i); > - if (name->type == GEN_DNS) { > - ASN1_STRING_print_ex(bio, name->d.ia5, ASN1_STRFLGS_ESC_CTRL| > - ASN1_STRFLGS_UTF8_CONVERT); > - n = BIO_pending(bio); > - if (n > 0) { > - cpp = (char **)apr_array_push(*ids); > - *cpp = apr_palloc(p, n+1); > - n = BIO_read(bio, *cpp, n); > - (*cpp)[n] = NUL; > + if (name->type == type) { > + if ((idx == -1) || (n == idx)) { > + switch (type) { > + case GEN_EMAIL: > + case GEN_DNS: > + utf8str = SSL_ASN1_STRING_to_utf8(p, name->d.ia5); > + 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) > + * GEN_URI (uniformResourceIdentifier) > + * GEN_IPADD (iPAddress) > + * GEN_RID (registeredID) > + */ > + break; > + } > } > + if ((idx != -1) && (n++ > idx)) > + break; > } > } > - BIO_free(bio); > - } > > - if (names) > sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); > + } > + > + return apr_is_empty_array(*entries) ? FALSE : TRUE; > +} > + > +/* return an array of (RFC 6125 coined) DNS-IDs and CN-IDs in a certificate > */ > +BOOL SSL_X509_getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids) > +{ > + X509_NAME *subj; > + int i = -1; > + > + /* First, the DNS-IDs (dNSName entries in the subjectAltName extension) > */ > + if (!x509 || > + (SSL_X509_getSAN(p, x509, GEN_DNS, -1, ids) == FALSE && !*ids)) { > + *ids = NULL; Why checking for FALSE and !*ids? Shouldn't the empty array cause a return of FALSE? > + return FALSE; > + } > > /* Second, the CN-IDs (commonName attributes in the subject DN) */ > subj = X509_get_subject_name(x509); > - i = -1; > while ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, i)) != -1) { > - cpp = (char **)apr_array_push(*ids); > - *cpp = SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, > i)); > + APR_ARRAY_PUSH(*ids, const char *) = > + SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i)); > } > > return apr_is_empty_array(*ids) ? FALSE : TRUE; > Regards Rüdiger
