+#ifdef LDAP_PF_INET6
+ if (name[0] == '[' && strchr(name, ']')) {
+ char *n2 = ldap_strdup(name+1);
+ *strchr(n2, ']') = 2;
+ if (inet_pton(AF_INET6, n2, &addr))
+ ntype = IS_IP6;
+ LDAP_FREE(n2);
+ } else
+#endif
+ if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
+ if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
+ }
+
+ i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
+ if (i >= 0) {
+ X509_EXTENSION *ex;
+ STACK_OF(GENERAL_NAME) *alt;
+
+ ex = X509_get_ext(x, i);
+ alt = X509V3_EXT_d2i(ex);
+ if (alt) {
+ int n, len1 = 0, len2 = 0;
+ char *domain = NULL;
+ GENERAL_NAME *gn;
+
+ if (ntype == IS_DNS) {
+ len1 = strlen(name);
+ domain = strchr(name, '.');
+ if (domain) {
+ len2 = len1 - (domain-name);
+ }
+ }
+ n = sk_GENERAL_NAME_num(alt);
+ for (i=0; i<n; i++) {
+ char *sn;
+ int sl;
+ gn = sk_GENERAL_NAME_value(alt, i);
+ if (gn->type == GEN_DNS) {
+ if (ntype != IS_DNS) continue;
+
+ sn = (char *) ASN1_STRING_data(gn->d.ia5);
+ sl = ASN1_STRING_length(gn->d.ia5);
+
+ /* ignore empty */
+ if (sl == 0) continue;
+
+ /* Is this an exact match? */
+ if ((len1 == sl) && !strncasecmp(name, sn, len1)) {
+ break;
+ }
+
+ /* Is this a wildcard match? */
+ if (domain && (sn[0] == '*') && (sn[1] == '.') &&
+ (len2 == sl-1) && !strncasecmp(domain, &sn[1], len2))
+ {
+ break;
+ }
+
+ } else if (gn->type == GEN_IPADD) {
+ if (ntype == IS_DNS) continue;
+
+ sn = (char *) ASN1_STRING_data(gn->d.ia5);
+ sl = ASN1_STRING_length(gn->d.ia5);
+
+#ifdef LDAP_PF_INET6
+ if (ntype == IS_IP6 && sl != sizeof(struct in6_addr)) {
+ continue;
+ } else
+#endif
+ if (ntype == IS_IP4 && sl != sizeof(struct in_addr)) {
+ continue;
+ }
+ if (!memcmp(sn, &addr, sl)) {
+ break;
+ }
+ }
+ }