On Mon, Jun 29, 2015 at 01:47:45PM +0200, Jan Pazdziora wrote:
> On Sun, Jun 28, 2015 at 05:11:57PM +0200, Kaspar Brand wrote:
> > On 22.06.2015 10:37, Jan Pazdziora wrote:
> > > Please find a new patch attached which I hope covers all the
> > > parts you've outlined, for SSL_CLIENT_SAN_OTHER_msUPN_*.
> > 
> > Thanks. Your implementation assumes that only a single otherName form
> > (msUPN) needs to be supported, but I would prefer to code it in a
> > somewhat more extensible way.
> > 
> > Does the attached patch work for you? As a practical way of
> 
> Yes it does.
> 
> My only question (and comments bellow) is about passing the oid rather
> than nid through the functions. I can see the string "id-on-dnsSRV"
> used twice in the patch in call OBJ_txt2nid and twice in call OBJ_txt2obj
> as well when ideally all which should be needed one
> OBJ_txt2nid("id-on-dnsSRV") and one OBJ_create if not found -- the rest
> could be done by comparing integers (nid). Unless I'm missing something
> about the oid/nid interaction.

Ah, now I see it -- you look at the semantics of oid to compare
value->type so nid would not be enough.

How about just passing char * and doing all the mapping logic
including possible OBJ_create in parse_otherName_value? My goal here
is to have all the "hard" work of determining the semantics isolated
in one place.

Please see patch attached.

-- 
Jan Pazdziora
Senior Principal Software Engineer, Identity Management Engineering, Red Hat
Index: modules/ssl/ssl_engine_init.c
===================================================================
--- modules/ssl/ssl_engine_init.c       (revision 1688186)
+++ modules/ssl/ssl_engine_init.c       (working copy)
@@ -1902,5 +1902,7 @@
 
     free_dh_params();
 
+    OBJ_cleanup();
+
     return APR_SUCCESS;
 }
Index: modules/ssl/ssl_engine_vars.c
===================================================================
--- modules/ssl/ssl_engine_vars.c       (revision 1688186)
+++ modules/ssl/ssl_engine_vars.c       (working copy)
@@ -665,6 +665,7 @@
 {
     int type, numlen;
     apr_array_header_t *entries;
+    const char *id = NULL;
 
     if (strcEQn(var, "Email_", 6)) {
         type = GEN_EMAIL;
@@ -674,6 +675,20 @@
         type = GEN_DNS;
         var += 4;
     }
+    else if (strcEQn(var, "OTHER_", 6)) {
+        type = GEN_OTHERNAME;
+        var += 6;
+        if (strEQn(var, "msUPN_", 6)) {
+            var += 6;
+            id = "msUPN";
+        }
+        else if (strEQn(var, "dnsSRV_", 7)) {
+            var += 7;
+            id = "id-on-dnsSRV";
+        }
+        else
+           return NULL;
+    }
     else
         return NULL;
 
@@ -682,7 +697,7 @@
     if ((numlen < 1) || (numlen > 4) || (numlen != strlen(var)))
         return NULL;
 
-    if (modssl_X509_getSAN(p, xs, type, atoi(var), &entries))
+    if (modssl_X509_getSAN(p, xs, type, id, atoi(var), &entries))
        /* return the first entry from this 1-element array */
        return APR_ARRAY_IDX(entries, 0, char *);
     else
@@ -1032,12 +1047,15 @@
     /* subjectAltName entries of the server certificate */
     xs = SSL_get_certificate(ssl);
     if (xs) {
-        if (modssl_X509_getSAN(p, xs, GEN_EMAIL, -1, &entries)) {
+        if (modssl_X509_getSAN(p, xs, GEN_EMAIL, NULL, -1, &entries)) {
             extract_san_array(t, "SSL_SERVER_SAN_Email", entries, p);
         }
-        if (modssl_X509_getSAN(p, xs, GEN_DNS, -1, &entries)) {
+        if (modssl_X509_getSAN(p, xs, GEN_DNS, NULL, -1, &entries)) {
             extract_san_array(t, "SSL_SERVER_SAN_DNS", entries, p);
         }
+        if (modssl_X509_getSAN(p, xs, GEN_DNS, "id-on-dnsSRV", -1, &entries)) {
+            extract_san_array(t, "SSL_SERVER_SAN_OTHER_dnsSRV", entries, p);
+        }
         /* no need to free xs (refcount does not increase) */
     }
 
@@ -1044,12 +1062,15 @@
     /* subjectAltName entries of the client certificate */
     xs = SSL_get_peer_certificate(ssl);
     if (xs) {
-        if (modssl_X509_getSAN(p, xs, GEN_EMAIL, -1, &entries)) {
+        if (modssl_X509_getSAN(p, xs, GEN_EMAIL, NULL, -1, &entries)) {
             extract_san_array(t, "SSL_CLIENT_SAN_Email", entries, p);
         }
-        if (modssl_X509_getSAN(p, xs, GEN_DNS, -1, &entries)) {
+        if (modssl_X509_getSAN(p, xs, GEN_DNS, NULL, -1, &entries)) {
             extract_san_array(t, "SSL_CLIENT_SAN_DNS", entries, p);
         }
+        if (modssl_X509_getSAN(p, xs, GEN_OTHERNAME, "msUPN", -1, &entries)) {
+            extract_san_array(t, "SSL_CLIENT_SAN_OTHER_msUPN", entries, p);
+        }
         X509_free(xs);
     }
 }
Index: modules/ssl/ssl_util_ssl.c
===================================================================
--- modules/ssl/ssl_util_ssl.c  (revision 1688186)
+++ modules/ssl/ssl_util_ssl.c  (working copy)
@@ -252,6 +252,46 @@
     return result;
 }
 
+static BOOL parse_otherName_value(apr_pool_t *p, OTHERNAME *othername,
+                                  const char *id,
+                                  apr_array_header_t **entries)
+{
+    if (!othername || !(othername->value) || (othername->type_id == NID_undef) 
||
+       !id || !*entries)
+       return FALSE;
+
+    /* 
+     * Currently supported otherName forms:
+     * - "msUPN" (1.3.6.1.4.1.311.20.2.3): Microsoft User Principal Name
+     * - "id-on-dnsSRV" (1.3.6.1.5.5.7.8.7): SRVName, as specified in RFC 4985
+     */
+
+    if (!strcmp(id, "msUPN")) {
+        const char *str;
+        if ((OBJ_obj2nid(othername->type_id) == NID_ms_upn) &&
+            (othername->value->type == V_ASN1_UTF8STRING) &&
+            (str = asn1_string_to_utf8(p, 
othername->value->value.utf8string))) {
+            APR_ARRAY_PUSH(*entries, const char *) = str;
+            return TRUE;
+        }
+    }
+    else if (!strcmp(id, "id-on-dnsSRV")) {
+        const char *str;
+        int nid = OBJ_txt2nid(id);
+        if (nid == NID_undef) {
+            nid = OBJ_create("1.3.6.1.5.5.7.8.7", "id-on-dnsSRV",
+                             "SRVName otherName form");
+        }
+        if ((OBJ_obj2nid(othername->type_id) == nid) &&
+            (othername->value->type == V_ASN1_IA5STRING) &&
+            (str = asn1_string_to_utf8(p, othername->value->value.ia5string))) 
{
+            APR_ARRAY_PUSH(*entries, const char *) = str;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 /* 
  * 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
@@ -258,13 +298,15 @@
  * of the n-th occurrence of that type only. Currently supported types:
  * GEN_EMAIL (rfc822Name)
  * GEN_DNS (dNSName)
+ * GEN_OTHERNAME (see parse_otherName_value for currently supported forms)
  */
-BOOL modssl_X509_getSAN(apr_pool_t *p, X509 *x509, int type, int idx,
-                        apr_array_header_t **entries)
+BOOL modssl_X509_getSAN(apr_pool_t *p, X509 *x509, int type, const char *id,
+                        int idx, apr_array_header_t **entries)
 {
     STACK_OF(GENERAL_NAME) *names;
 
-    if (!x509 || (type < GEN_OTHERNAME) || (type > GEN_RID) || (idx < -1) ||
+    if (!x509 || (type < GEN_OTHERNAME) || (type == GEN_OTHERNAME && !id) ||
+        (type > GEN_RID) || (idx < -1) ||
         !(*entries = apr_array_make(p, 0, sizeof(char *)))) {
         *entries = NULL;
         return FALSE;
@@ -277,33 +319,40 @@
 
         for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
             name = sk_GENERAL_NAME_value(names, i);
-            if (name->type == type) {
-                if ((idx == -1) || (n == idx)) {
-                    switch (type) {
-                    case GEN_EMAIL:
-                    case GEN_DNS:
-                        utf8str = 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 (name->type != type)
+                continue;
+
+            switch (type) {
+            case GEN_EMAIL:
+            case GEN_DNS:
+                if (((idx == -1) || (n == idx)) &&
+                    (utf8str = asn1_string_to_utf8(p, name->d.ia5))) {
+                    APR_ARRAY_PUSH(*entries, const char *) = utf8str;
                 }
-                if ((idx != -1) && (n++ > idx))
-                   break;
+                n++;
+                break;
+            case GEN_OTHERNAME:
+                if (((idx == -1) || (n == idx))) {
+                    if (parse_otherName_value(p, name->d.otherName, id, 
entries))
+                        n++;
+                }
+                break;
+            default:
+                /*
+                 * Not implemented right now:
+                 * 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;
         }
 
         sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
@@ -320,7 +369,7 @@
 
     /* First, the DNS-IDs (dNSName entries in the subjectAltName extension) */
     if (!x509 ||
-        (modssl_X509_getSAN(p, x509, GEN_DNS, -1, ids) == FALSE && !*ids)) {
+        (modssl_X509_getSAN(p, x509, GEN_DNS, NULL, -1, ids) == FALSE && 
!*ids)) {
         *ids = NULL;
         return FALSE;
     }
Index: modules/ssl/ssl_util_ssl.h
===================================================================
--- modules/ssl/ssl_util_ssl.h  (revision 1688186)
+++ modules/ssl/ssl_util_ssl.h  (working copy)
@@ -65,7 +65,8 @@
 BOOL        modssl_X509_getBC(X509 *, int *, int *);
 char       *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY 
*xsne);
 char       *modssl_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int);
-BOOL        modssl_X509_getSAN(apr_pool_t *, X509 *, int, int, 
apr_array_header_t **);
+BOOL        modssl_X509_getSAN(apr_pool_t *, X509 *, int, const char *, int,
+                apr_array_header_t **);
 BOOL        modssl_X509_match_name(apr_pool_t *, X509 *, const char *, BOOL, 
server_rec *);
 char       *modssl_SSL_SESSION_id2sz(unsigned char *, int, char *, int);
 

Reply via email to