httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mar...@apache.org
Subject svn commit: r220307 - in /httpd/httpd/trunk/modules: metadata/mod_setenvif.c ssl/mod_ssl.c ssl/mod_ssl.h ssl/ssl_expr_eval.c
Date Fri, 22 Jul 2005 12:11:56 GMT
Author: martin
Date: Fri Jul 22 05:11:55 2005
New Revision: 220307

URL: http://svn.apache.org/viewcvs?rev=220307&view=rev
Log:
Allow extraction of the values of SSL certificate extensions into
environment variables, so that their value can be used by any
module that is aware of environment variables, as in:

  SetEnvIf OID("2.16.840.1.113730.1.13") "(.*) Generated (Certificate)" ca=$1
sets
  ca=TinyCA
if the cert was issued by TinyCA.

Similarly,
  SetenvIf OID("2.16.840.1.113730.1.13") "(.*)" NetscapeComment=$1
will set $NetscapeComment to the whole string.

It is technically allowed to have multiple instances of an extension
field, all with the same oid. In this case, the environment variable
will be set to the list of all fields, separated by commas.

The [PATCH] uses a cross-module call from mod_setenvif to
mod_ssl (the latter may also be missing: in this case the
variable will never be set). It calls a common function
in the ssl module that is also used for the SSLRequire
directive's test.

Modified:
    httpd/httpd/trunk/modules/metadata/mod_setenvif.c
    httpd/httpd/trunk/modules/ssl/mod_ssl.c
    httpd/httpd/trunk/modules/ssl/mod_ssl.h
    httpd/httpd/trunk/modules/ssl/ssl_expr_eval.c

Modified: httpd/httpd/trunk/modules/metadata/mod_setenvif.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/metadata/mod_setenvif.c?rev=220307&r1=220306&r2=220307&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/metadata/mod_setenvif.c (original)
+++ httpd/httpd/trunk/modules/metadata/mod_setenvif.c Fri Jul 22 05:11:55 2005
@@ -102,7 +102,8 @@
     SPECIAL_REQUEST_URI,
     SPECIAL_REQUEST_METHOD,
     SPECIAL_REQUEST_PROTOCOL,
-    SPECIAL_SERVER_ADDR
+    SPECIAL_SERVER_ADDR,
+    SPECIAL_OID_VALUE
 };
 typedef struct {
     char *name;                 /* header name */
@@ -120,6 +121,12 @@
 } sei_cfg_rec;
 
 module AP_MODULE_DECLARE_DATA setenvif_module;
+#if (MODULE_MAGIC_NUMBER_MAJOR > 20020903)
+#include "mod_ssl.h"
+#else
+APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_extlist_by_oid, (request_rec *r, const
char *oidstr));
+#endif
+static APR_OPTIONAL_FN_TYPE(ssl_extlist_by_oid) *ssl_extlist_by_oid_func = NULL;
 
 /*
  * These routines, the create- and merge-config functions, are called
@@ -345,6 +352,31 @@
         else if (!strcasecmp(fname, "server_addr")) {
             new->special_type = SPECIAL_SERVER_ADDR;
         }
+        else if (!strncasecmp(fname, "oid(",4)) {
+            ap_regmatch_t match[AP_MAX_REG_MATCH];
+
+            new->special_type = SPECIAL_OID_VALUE;
+
+            /* Syntax check and extraction of the OID as a regex: */
+            new->pnamereg = ap_pregcomp(cmd->pool,
+                                        "^oid\\(\"?([0-9.]+)\"?\\)$",
+                                        (AP_REG_EXTENDED // | AP_REG_NOSUB
+                                         | AP_REG_ICASE));
+            /* this can never happen, as long as pcre works:
+              if (new->pnamereg == NULL)
+                    return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                                       "OID regex could not be compiled.", NULL);
+             */
+            if (ap_regexec(new->pnamereg, fname, AP_MAX_REG_MATCH, match, 0) == AP_REG_NOMATCH)
{
+                return apr_pstrcat(cmd->pool, cmd->cmd->name,
+                                       "OID syntax is: oid(\"1.2.3.4.5\"); error in: ",
+                                       fname, NULL);
+            }
+            new->pnamereg = NULL;
+            /* The name field is used for the stripped oid string */
+            new->name = fname = apr_pstrdup(cmd->pool, fname+match[1].rm_so);
+            fname[match[1].rm_eo - match[1].rm_so] = '\0';
+        }
         else {
             new->special_type = SPECIAL_NOT;
             /* Handle fname as a regular expression.
@@ -475,6 +507,8 @@
          * same header.  Remember we don't need to strcmp the two header
          * names because we made sure the pointers were equal during
          * configuration.
+         * In the case of SPECIAL_OID_VALUE values, each oid string is
+         * dynamically allocated, thus there are no duplicates.
          */
         if (b->name != last_name) {
             last_name = b->name;
@@ -498,6 +532,34 @@
             case SPECIAL_REQUEST_PROTOCOL:
                 val = r->protocol;
                 break;
+            case SPECIAL_OID_VALUE:
+                /* If mod_ssl is not loaded, the accessor function is NULL */
+                if (ssl_extlist_by_oid_func != NULL)
+                {
+                    apr_array_header_t *oid_array;
+                    char **oid_value;
+                    int j, len = 0;
+                    char *retval = NULL;
+
+                    /* The given oid can occur multiple times. Concatenate the values */
+                    if ((oid_array = ssl_extlist_by_oid_func(r, b->name)) != NULL) {
+                        oid_value = (char **) oid_array->elts;
+                        /* pass 1: determine the size of the string */
+                        for (len=j=0; j < oid_array->nelts; j++) {
+                          len += strlen(oid_value[j]) + 1; /* +1 for ',' or terminating NIL
*/
+                        }
+                        retval = apr_palloc(r->pool, len);
+                        /* pass 2: fill the string */
+                        for (j=0; j < oid_array->nelts; j++) {
+                          if (j > 0) {
+                              strcat(retval, ",");
+                          }
+                          strcat(retval, oid_value[j]);
+                        }
+                    }
+                    val = retval;
+                }
+                break;
             case SPECIAL_NOT:
                 if (b->pnamereg) {
                     /* Matching headers_in against a regex. Iterate through
@@ -568,10 +630,19 @@
     return DECLINED;
 }
 
+static int
+setenvif_post_config()
+{
+    ssl_extlist_by_oid_func = APR_RETRIEVE_OPTIONAL_FN(ssl_extlist_by_oid);
+    return OK;
+}
+
 static void register_hooks(apr_pool_t *p)
 {
     ap_hook_header_parser(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
+    /* post config handling */
+    ap_hook_post_config(setenvif_post_config, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 module AP_MODULE_DECLARE_DATA setenvif_module =

Modified: httpd/httpd/trunk/modules/ssl/mod_ssl.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/ssl/mod_ssl.c?rev=220307&r1=220306&r2=220307&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/mod_ssl.c (original)
+++ httpd/httpd/trunk/modules/ssl/mod_ssl.c Fri Jul 22 05:11:55 2005
@@ -503,6 +503,8 @@
 
     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
+
+    APR_REGISTER_OPTIONAL_FN(ssl_extlist_by_oid);
 }
 
 module AP_MODULE_DECLARE_DATA ssl_module = {

Modified: httpd/httpd/trunk/modules/ssl/mod_ssl.h
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/ssl/mod_ssl.h?rev=220307&r1=220306&r2=220307&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/mod_ssl.h (original)
+++ httpd/httpd/trunk/modules/ssl/mod_ssl.h Fri Jul 22 05:11:55 2005
@@ -49,4 +49,7 @@
 
 APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
 
+extern apr_array_header_t *ssl_extlist_by_oid(request_rec *r, const char *oidstr);
+APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_extlist_by_oid, (request_rec *r, const
char *oidstr));
+
 #endif /* __MOD_SSL_H__ */

Modified: httpd/httpd/trunk/modules/ssl/ssl_expr_eval.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/ssl/ssl_expr_eval.c?rev=220307&r1=220306&r2=220307&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_expr_eval.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_expr_eval.c Fri Jul 22 05:11:55 2005
@@ -36,7 +36,7 @@
 
 static BOOL  ssl_expr_eval_comp(request_rec *, ssl_expr *);
 static char *ssl_expr_eval_word(request_rec *, ssl_expr *);
-static BOOL  ssl_expr_eval_oid(const char *w, request_rec *r, const char *oidstr);
+static BOOL  ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr);
 static char *ssl_expr_eval_func_file(request_rec *, char *);
 static int   ssl_expr_eval_strcmplex(char *, char *);
 
@@ -121,7 +121,7 @@
                 if (op == op_OidListElement) {
                     char *w3 = ssl_expr_eval_word(r, e3);
 
-                    found = ssl_expr_eval_oid(w1, r, w3);
+                    found = ssl_expr_eval_oid(r, w1, w3);
 
                     /* There will be no more nodes on the list, so the result is authoritative
*/
                     break;
@@ -198,33 +198,35 @@
     }
 }
 
-static BOOL ssl_expr_eval_oid(const char *word, request_rec *r, const char *oidstr)
+#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)
 {
-    SSLConnRec *sslconn = myConnConfig(r->connection);
-    SSL *ssl;
+    int count = 0, j;
     X509 *xs = NULL;
     ASN1_OBJECT *oid;
-    int count = 0, j;
-    BOOL result = FALSE;
-
-    if (!oidstr || !sslconn || !sslconn->ssl)
-        return FALSE;
+    apr_array_header_t *val_array;
+    SSLConnRec *sslconn = myConnConfig(r->connection);
 
-    ssl = sslconn->ssl;
+    /* trivia */
+    if (oidstr == NULL || sslconn == NULL || sslconn->ssl == NULL)
+        return NULL;
 
-    oid = OBJ_txt2obj(oidstr, 1);
-    if (!oid) {
+    /* Determine the oid we are looking for */
+    if ((oid = OBJ_txt2obj(oidstr, 1)) == NULL) {
         ERR_clear_error();
-        return FALSE;
+        return NULL;
     }
 
-    xs = SSL_get_peer_certificate(ssl);
-    if (xs == NULL) {
-        return FALSE;
+    /* are there any extensions in the cert? */
+    if ((xs = SSL_get_peer_certificate(sslconn->ssl)) == NULL ||
+        (count = X509_get_ext_count(xs)) == 0) {
+        return NULL;
     }
 
-    count = X509_get_ext_count(xs);
+    val_array = apr_array_make(r->pool, NUM_OID_ELTS, sizeof(char *));
 
+    /* Loop over all extensions, extract the desired oids */
     for (j = 0; j < count; j++) {
         X509_EXTENSION *ext = X509_get_ext(xs, j);
 
@@ -233,21 +235,45 @@
 
             if (X509V3_EXT_print(bio, ext, 0, 0) == 1) {
                 BUF_MEM *buf;
+                char **new = apr_array_push(val_array);
 
                 BIO_get_mem_ptr(bio, &buf);
 
-                if (strcmp(word, buf->data) == 0)
-                    result = TRUE;
+                *new = apr_pstrdup(r->pool, buf->data);
             }
 
             BIO_vfree(bio);
-            if (result != FALSE)
-                break;
         }
     }
 
     X509_free(xs);
     ERR_clear_error();
+
+    if (val_array->nelts == 0)
+        return NULL;
+    else
+        return val_array;
+}
+
+static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, const char *oidstr)
+{
+    SSLConnRec *sslconn = myConnConfig(r->connection);
+    int j;
+    BOOL result = FALSE;
+    apr_array_header_t *oid_array;
+    char **oid_value;
+
+    if (NULL == (oid_array = ssl_extlist_by_oid(r, oidstr))) {
+        return FALSE;
+    }
+
+    oid_value = (char **) oid_array->elts;
+    for (j = 0; j < oid_array->nelts; j++) {
+        if (strcmp(word, oid_value[j]) == 0) {
+            result = TRUE;
+            break;
+        }
+    }
     return result;
 }
 



Mime
View raw message