httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dirk-Willem van Gulik <di...@webweaving.org>
Subject Adding OID group support to mod_ssl
Date Sun, 07 Aug 2005 17:05:48 GMT

Martin, David,

See below a patch which now works with multiple group membership. That is
IMHO as far as apache should go - anything beyond this should really be
done through OpenSSL and some ASN1 'format' string passed along. Once you
start looping through more complex sets one finds that mod_auth_svn
requests more than one OID over time; or several times for the same one
within local redirects. So at some point caching this data may make sense.

Dw.

Index: ssl_expr_eval.c
===================================================================
--- ssl_expr_eval.c     (revision 226665)
+++ ssl_expr_eval.c     (working copy)
@@ -40,6 +40,54 @@
 static char *ssl_expr_eval_func_file(request_rec *, char *);
 static int   ssl_expr_eval_strcmplex(char *, char *);

+#define AP_ASN1_ISPRINTABLE(x) (\
+       (x) == V_ASN1_IA5STRING ||\
+       (x) == V_ASN1_T61STRING || \
+       (x) == V_ASN1_PRINTABLESTRING || \
+       (x) == V_ASN1_UTF8STRING)
+
+/* Perl code to generate groups or just single strings..
+
+#!/usr/bin/perl
+#
+use Convert::ASN1;
+use strict;
+$|++;
+
+my @groups = @ARGV
+        or die "Syntax: $0 <group1> ...\n";
+
+my $asn = Convert::ASN1->new;
+
+# The difference between SEQUENCE and SET is in the order of transmission
+# of the fields: for SEQUENCE, a sender is required to transmit them in
+# the order listed in the notation; for SET, the order of transmission is
+# an implementation option for the sender. The mod_ssl module detects
+# both types.
+#
+my $bytes='';
+if ($#groups) {
+       $asn->prepare('str SET OF STRING');     # we're not order
sensitive.
+       $bytes = $asn->encode(str => \@groups)
+               or die $!;
+} else {
+       $asn->prepare('str STRING');
+       $bytes = $asn->encode(str => $groups[0])
+               or die $!;
+}
+
+my $bytes = $asn->encode(str => \@groups)
+        or die $!;
+
+print "Line to include in OPENSSL config:\n";
+
+print "DER";
+map { printf ":%02X",$_; } unpack('C*', $bytes);print "\n";
+
+exit 0;
+
+*/
+
 BOOL ssl_expr_eval(request_rec *r, ssl_expr *node)
 {
     switch (node->node_op) {
@@ -199,7 +247,6 @@
 }

 #define NUM_OID_ELTS 8 /* start with 8 oid slots, resize when needed */
-
 apr_array_header_t *ssl_extlist_by_oid(request_rec *r, const char
*oidstr)
 {
     int count = 0, j;
@@ -229,7 +276,28 @@
     /* Loop over all extensions, extract the desired oids */
     for (j = 0; j < count; j++) {
         X509_EXTENSION *ext = X509_get_ext(xs, j);
+#if 0
+       {
+               char buff[16*1024];
+                BUF_MEM *buf;
+               BIO *bio = BIO_new(BIO_s_mem());
+               OBJ_obj2txt(buff, sizeof(buff), ext->object, 0);

+               if (X509V3_EXT_print(bio, ext, /* X509V3_EXT_ERROR_UNKNOWN */ X509V3_EXT_PARSE_UNKNOWN
/*  X509V3_EXT_DUMP_UNKNOWN */, 0) == 1) {
+                       BIO_get_mem_ptr(bio, &buf);
+
+                       /* XXX for some reason the PARSE_UNK do not have a trailing \0 */
+                       buf->data[ buf->length -1 ] = 0;
+
+                       ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Extension
'%s': %s", buff,buf->data);
+               };
+               BIO_vfree(bio);
+
+       };
+#endif
+/* XXX not the most efficient way of doing this - we propably want to cache
+ *     the strings extracted for repeated lookups on new oidstr's.
+ */
         if (OBJ_cmp(ext->object, oid) == 0) {
             BIO *bio = BIO_new(BIO_s_mem());

@@ -238,13 +306,38 @@
                 char **new = apr_array_push(val_array);

                 BIO_get_mem_ptr(bio, &buf);
-
                 *new = apr_pstrdup(r->pool, buf->data);
-            }
-
+               ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                       "X509v3 extension %s == '%s' found.", oidstr, *new);
+            } else
+           /* The above X509V3_EXT_print() only captures OID's which are a) hardcoded in
openssl its objects.txt
+             * file, b) referenced in the asn1 parsing and c) listed as valid in the 509v3
extension code. Below
+            * we simply also accept any fields which have a normalish string in them.
+             */
+           if (AP_ASN1_ISPRINTABLE(ext->value->data[0])) {
+               char **new = apr_array_push(val_array);
+                *new = apr_pstrmemdup(r->pool, &(ext->value->data[2]), ext->value->data[1]);
+               ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                       "Raw X509v3 extension %s == <%s> found in client certificate",
oidstr, *new);
+           } else
+           if ((ext->value->data[0] == V_ASN1_SET || ext->value->data[0] == V_ASN1_SEQUENCE)
&&
+               (ext->value->data[1]>3) && (AP_ASN1_ISPRINTABLE(ext->value->data[2])))
+           {
+               int len = ext->value->data[1];
+               int i = 2;
+               while(i < len) {
+                       if (AP_ASN1_ISPRINTABLE(ext->value->data[i])) {
+                               char **new = apr_array_push(val_array);
+                                *new = apr_pstrmemdup(r->pool, &(ext->value->data[i+2]),
ext->value->data[i+1]);
+                               ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                                       "Raw set of X509v3 extension %s == <%s> found
in client certificate", oidstr, *new);
+                       }
+                       i += ext->value->data[i+1] + 2;
+               }
+           }
             BIO_vfree(bio);
         }
-    }
+    } /* loop over all extensions */

Mime
View raw message