On Thu, Oct 15, 2009 at 03:43:36PM +0200, Graham Leggett wrote: > Joe Orton wrote: > > > Are you trying to match against the contents of the (single) extKeyUsage > > extension? That isn't how PeerExtList works, or at least, was written > > and documented to work, AFAICT: PeerExtList will return a list of the > > value of each extension in the cert with the given OID. > > > > Does that make sense? This is just from reading the trunk code/docs, I > > may be missing something. > > > > To solve your problem: parsing the string which OpenSSL spits out as a > > representation of the extKeyUsage list would sound a bit hacky. I guess > > I'd recommend doing it as a set of custom variables: > > > > SSL_{CLIENT,SERVER}_EXT_KEYUSAGE_{CLIENT_AUTH,EMAIL_PROTECTION,...} > > > > which evaluate to 0 or 1 depending on whether the indicated usage is > > present in the extKeyUsage extension. Would something like that work? > > The problem I'm trying to solve is that we'll be issuing certs with our > own extKeyUsage values, and I would imagine they would be inventing > values with custom oids for various purposes, so something generic would > be needed, as opposed to fixed "well known" oids.
OK, fair enough. So, maybe just a function (bleh) which takes an OID and returns true/false if there is an extended key usage extension present with the given key purpose OID listed? SSLRequire PeerKeyPurpose("OID") > One of the key things I was struggling with was trying to understand how > it currently was supposed to work, so I didn't hack it in the wrong > direction. > > >From what I can see, we have a set of oid values (which in this case, > extKeyUsage, which contains just one value: "A,B,C") associated with a > key, which can in turn can contain a set of values (which in this case > contains "A", "B" and "C"). Kind of. A certificate can have any number of extensions. Each extension is a (key, value) pair, where the key is an OID, and the value is an ASN.1 structure specific to the key. When evaluating "foo in PeerExtList(bar)", mod_ssl will look at each extension with key OID 'bar' and transform the associated ASN.1 structure to a string, then return true if any of those strings match 'foo'. The "extended key usage" extension is defined simply as a list of OIDs - from the ASN.1 in RFC 5280: ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId KeyPurposeId ::= OBJECT IDENTIFIER when you use PeerExtList on that structure, OpenSSL will do something random, unspecified, and possibly useful to that ASN.1 structure, to transform it into a string. From your testing results, it makes a comma-separated string of the OID numbers. The wrong way to solve this is to have OpenSSL go through all those hoops to transform the ASN.1 extension value into a string, parse the string, and then match against the returned OIDs. The way OpenSSL does that is unspecified and may change - maybe it will use spaces to separate the OIDs in a future version, for example. Who knows. The right way to solve this is to extract the EXTENDED_KEY_USAGE OpenSSL data structure and match against the OIDs, without converting it to a string. SSL_X509_isSGC has an example of how to do this, though uses an older extension API; ssl_engine_ocsp.c:extract_responder_uri is a better example of using the OpenSSL extension API. > Looking further at the expression syntax of SSLRequire, it looks like > this might do the trick: > > SSLRequire "1.3.6.1.5.5.7.3.4" in { PeerExtList("2.5.29.37") } This won't match the grammar - the docs do show this accurately, it must be SSLRequire "foo" in PeerExtList("..."), if you look at the code in ssl_expr_eval.c it has a special case for PeerExtList in the code handling the "in" operator. Regards, Joe