On Tue, Sep 20, 2005 at 05:33:30PM +0100, Joe Orton wrote:
> > SetEnvIf SSL_PeerExtList("1.3.6.1.4.1.18060.1") \
> > "(committers|administrators)" \
> > ThisUserHasAValidCert=$1
> >
> > Later on, you can control access (in dir context, if desired) by
> >
> > allow from env=ThisUserHasAValidCert
>
> That's just SSLRequire reimplemented badly, as you say. What's the real
> use-case for this feature, what problem are you trying to solve?
If used for "allow from env=", you are right. But environment variables
do have a much more global usage scenario.
I see a usage scenario in anything from CGIs (and .shtml / .php / .pl)
to custom error documents, or rewriting and filtering. The patch
just extends the already existing availability of standard predefined
variables which allow access to the cert's main data to also get
access to any other string data contained in the cert's extensions
(without having to modify each and every Apache module that needs
access to those strings).
For the single case of an internal SSL renegotiation in mod_ssl during
response processing, there should of course...
a) be a CAVEAT section in the docs for mod_ssl and/or mod_setenvif
that describe the problem
b) be a discussion about the side effects of such a renegotiation
on the already-sampled request status (what aspect of the already
collected infomation has been invaidated by the renegotiation, and
how can it be updated?)
I attached a patch to the xml docs, and an updated version of the patch
you provided, modified for a stricter syntax check.
Martin
--
<[EMAIL PROTECTED]> | Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-48332 | 81730 Munich, Germany
Index: mod/mod_setenvif.xml
===================================================================
--- mod/mod_setenvif.xml (Revision 290923)
+++ mod/mod_setenvif.xml (Arbeitskopie)
@@ -184,13 +184,21 @@
used for the <em>attribute</em>.</li>
<li>
- A reference to an extension of an SSL client certificate, located by
- its object id <em>oid</em>.
- If a non-SSL request, or in absense of the configured <em>oid</em>,
- no variable will be set. If the <em>oid</em> is found multiple times,
- the individual strings will be concatenated, separated by a comma
<code>','</code>.
- The <em>oid</em> should reference a string-valued extension.
-</li>
+ A reference to an X.509 extension in an SSL client certificate,
+ identified by the reference
+ <code>SSL_PeerExtList(<em>oid</em>)</code> specifying its object id.
+ In a non-SSL request, or in absence of a client certificate or of the
+ given <em>oid</em> in the client certificate, no variable will be
+ set. If the <em>oid</em> is found multiple times, the individual
+ strings will be concatenated, separated by a comma <code>','</code>.
+ The object id <em>oid</em> should reference a string-valued
+ extension.<br />
+ Note that, if you use the "<directive>SSLVerifyClient</directive>
+ require" directive in a <code>.htaccess</code> context, (because of
+ the internal order of evaluation and the neccessary SSL
+ renegotiation) the variable will not reflect the actual state of the
+ certificate, but the state at the beginning of the request before the
+ SSL renegotiation.</li>
</ol>
<p>The second argument (<em>regex</em>) is a <glossary
@@ -228,7 +236,7 @@
:<br />
SetEnvIf object_is_image xbm XBIT_PROCESSING=1<br />
:<br />
- SetEnvIf OID("2.16.840.1.113730.1.13") "(.*)" NetscapeComment=$1<br />
+ SetEnvIf SSL_PeerExtList("2.16.840.1.113730.1.13") "(.*)"
NetscapeComment=$1<br />
:<br />
SetEnvIf ^TS* ^[a-z].* HAVE_TS<br />
</example>
Index: modules/metadata/mod_setenvif.c
===================================================================
--- modules/metadata/mod_setenvif.c (Revision 290463)
+++ modules/metadata/mod_setenvif.c (Arbeitskopie)
@@ -104,7 +104,7 @@
SPECIAL_REQUEST_METHOD,
SPECIAL_REQUEST_PROTOCOL,
SPECIAL_SERVER_ADDR,
- SPECIAL_OID_VALUE
+ SPECIAL_SSL_PEEREXTLIST
};
typedef struct {
char *name; /* header name */
@@ -349,30 +349,29 @@
else if (!strcasecmp(fname, "server_addr")) {
new->special_type = SPECIAL_SERVER_ADDR;
}
- else if (!strncasecmp(fname, "oid(",4)) {
+ else if (!strncasecmp(fname,
"SSL_PeerExtList(",sizeof("SSL_PeerExtList(")-1)) {
ap_regmatch_t match[AP_MAX_REG_MATCH];
- new->special_type = SPECIAL_OID_VALUE;
+ new->special_type = SPECIAL_SSL_PEEREXTLIST;
- /* Syntax check and extraction of the OID as a regex: */
+ /* Syntax check and extraction of the SSL_PeerExtList as a regex:
*/
new->pnamereg = ap_pregcomp(cmd->pool,
- "^oid\\(\"?([0-9.]+)\"?\\)$",
+
"^SSL_PeerExtList\\(\"?([0-9][0-9.]+[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);
+ "SSL_PeerExtList 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: ",
+ "invalid ssl_peerextlist() syntax 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';
+ /* The name field is used for the stripped PeerExt string */
+ new->name = fname = apr_pstrndup(cmd->pool, fname+match[1].rm_so,
match[1].rm_eo - match[1].rm_so);
}
else {
new->special_type = SPECIAL_NOT;
@@ -504,8 +503,9 @@
* 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.
+ * In the case of SPECIAL_SSL_PEEREXTLIST values, each
+ * extension list is dynamically allocated, thus there are no
+ * duplicates.
*/
if (b->name != last_name) {
last_name = b->name;
@@ -529,33 +529,17 @@
case SPECIAL_REQUEST_PROTOCOL:
val = r->protocol;
break;
- case SPECIAL_OID_VALUE:
+ case SPECIAL_SSL_PEEREXTLIST:
/* If mod_ssl is not loaded, the accessor function is NULL */
if (ssl_ext_list_func != NULL)
{
- apr_array_header_t *oid_array;
- char **oid_value;
- int j, len = 0;
- char *retval = NULL;
+ apr_array_header_t *peerext_array;
- /* The given oid can occur multiple times. Concatenate the
values */
- if ((oid_array = ssl_ext_list_func(r->pool, r->connection,
1,
+ /* The given Peer Extension can occur multiple times.
Concatenate the values */
+ if ((peerext_array = ssl_ext_list_func(r->pool,
r->connection, 1,
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 = apr_array_pstrcat(r->pool, peerext_array, ',');
}
- val = retval;
}
break;
case SPECIAL_NOT:
Index: modules/metadata/mod_setenvif.c
===================================================================
--- modules/metadata/mod_setenvif.c (Revision 290463)
+++ modules/metadata/mod_setenvif.c (Arbeitskopie)
@@ -104,7 +104,7 @@
SPECIAL_REQUEST_METHOD,
SPECIAL_REQUEST_PROTOCOL,
SPECIAL_SERVER_ADDR,
- SPECIAL_OID_VALUE
+ SPECIAL_SSL_PEEREXTLIST
};
typedef struct {
char *name; /* header name */
@@ -349,30 +349,40 @@
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];
+ else if (!strncasecmp(fname, "ssl_peerextlist(",
+ sizeof("ssl_peerextlist(")-1)) {
+ const char *oid, *oidend;
+ int quoted = 0;
- new->special_type = SPECIAL_OID_VALUE;
+ new->special_type = SPECIAL_SSL_PEEREXTLIST;
- /* 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) {
+ oid = fname + sizeof("ssl_peerextlist(")-1;
+ oidend = &oid[strlen(oid)-1];
+
+ if (*oidend != ')') {
+ /* error: ')' missing */
+ oidend = NULL;
+ }
+ else {
+ /* skip over quotes if present */
+ quoted = (oid[0] == '"' && oidend[-1] == '"');
+ if (quoted) {
+ oid++;
+ --oidend;
+ }
+ else if (oid[0] == '"' || oidend[-1] == '"') {
+ oidend = NULL;
+ }
+ }
+
+ /* Error cases: missing ')', unpaired quoting, empty oid name */
+ if (!oidend || oidend <= oid) {
return apr_pstrcat(cmd->pool, cmd->cmd->name,
- "OID syntax is: oid(\"1.2.3.4.5\");
error in: ",
+ ": invalid ssl_peerextlist() syntax 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';
+ /* The name field is used for the stripped PeerExt string */
+ new->name = fname = apr_pstrndup(cmd->pool, oid, oidend - oid);
}
else {
new->special_type = SPECIAL_NOT;
@@ -504,8 +514,9 @@
* 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.
+ * In the case of SPECIAL_SSL_PEEREXTLIST values, each
+ * extension list is dynamically allocated, thus there are no
+ * duplicates.
*/
if (b->name != last_name) {
last_name = b->name;
@@ -529,33 +540,17 @@
case SPECIAL_REQUEST_PROTOCOL:
val = r->protocol;
break;
- case SPECIAL_OID_VALUE:
+ case SPECIAL_SSL_PEEREXTLIST:
/* If mod_ssl is not loaded, the accessor function is NULL */
if (ssl_ext_list_func != NULL)
{
- apr_array_header_t *oid_array;
- char **oid_value;
- int j, len = 0;
- char *retval = NULL;
+ apr_array_header_t *peerext_array;
- /* The given oid can occur multiple times. Concatenate the
values */
- if ((oid_array = ssl_ext_list_func(r->pool, r->connection,
1,
+ /* The given Peer Extension can occur multiple times.
Concatenate the values */
+ if ((peerext_array = ssl_ext_list_func(r->pool,
r->connection, 1,
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 = apr_array_pstrcat(r->pool, peerext_array, ',');
}
- val = retval;
}
break;
case SPECIAL_NOT: