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);