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

Reply via email to