static int tlso_session_peer_dn( tls_session *sess, struct berval *der_dn ) { tlso_session *s = (tlso_session *)sess; X509 *x = tlso_get_cert( s ); X509_NAME *xn; if ( !x ) return LDAP_INVALID_CREDENTIALS; xn = X509_get_subject_name(x); #if OPENSSL_VERSION_NUMBER < 0x10100000 der_dn->bv_len = i2d_X509_NAME( xn, NULL ); der_dn->bv_val = xn->bytes->data; #else { size_t len = 0; der_dn->bv_val = NULL; X509_NAME_get0_der( (const unsigned char **)&der_dn->bv_val, &len, xn ); der_dn->bv_len = len; } #endif X509_free(x); return 0; }
static int tlso_session_peer_dn( tls_session *sess, struct berval *der_dn ) { tlso_session *s = (tlso_session *)sess; X509 *x = tlso_get_cert( s ); X509_NAME *xn; if ( !x ) return LDAP_INVALID_CREDENTIALS; xn = X509_get_subject_name(x); der_dn->bv_len = i2d_X509_NAME( xn, NULL ); der_dn->bv_val = xn->bytes->data; X509_free(x); return 0; }
static int tlso_session_chkhost( LDAP *ld, tls_session *sess, const char *name_in ) { tlso_session *s = (tlso_session *)sess; int i, ret = LDAP_LOCAL_ERROR; X509 *x; const char *name; char *ptr; int ntype = IS_DNS, nlen; #ifdef LDAP_PF_INET6 struct in6_addr addr; #else struct in_addr addr; #endif if( ldap_int_hostname && ( !name_in || !strcasecmp( name_in, "localhost" ) ) ) { name = ldap_int_hostname; } else { name = name_in; } nlen = strlen(name); x = tlso_get_cert(s); if (!x) { Debug( LDAP_DEBUG_ANY, "TLS: unable to get peer certificate.\n", 0, 0, 0 ); /* If this was a fatal condition, things would have * aborted long before now. */ return LDAP_SUCCESS; } #ifdef LDAP_PF_INET6 if (inet_pton(AF_INET6, name, &addr)) { ntype = IS_IP6; } 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, len2 = 0; char *domain = NULL; GENERAL_NAME *gn; if (ntype == IS_DNS) { domain = strchr(name, '.'); if (domain) { len2 = nlen - (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 ((nlen == sl) && !strncasecmp(name, sn, nlen)) { 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; } } } GENERAL_NAMES_free(alt); if (i < n) { /* Found a match */ ret = LDAP_SUCCESS; } } } if (ret != LDAP_SUCCESS) { X509_NAME *xn; X509_NAME_ENTRY *ne; ASN1_OBJECT *obj; ASN1_STRING *cn = NULL; int navas; /* find the last CN */ obj = OBJ_nid2obj( NID_commonName ); if ( !obj ) goto no_cn; /* should never happen */ xn = X509_get_subject_name(x); navas = X509_NAME_entry_count( xn ); for ( i=navas-1; i>=0; i-- ) { ne = X509_NAME_get_entry( xn, i ); if ( !OBJ_cmp( X509_NAME_ENTRY_get_object(ne), obj )) { cn = X509_NAME_ENTRY_get_data( ne ); break; } } if( !cn ) { no_cn: Debug( LDAP_DEBUG_ANY, "TLS: unable to get common name from peer certificate.\n", 0, 0, 0 ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: unable to get CN from peer certificate")); } else if ( cn->length == nlen && strncasecmp( name, (char *) cn->data, nlen ) == 0 ) { ret = LDAP_SUCCESS; } else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) { char *domain = strchr(name, '.'); if( domain ) { int dlen; dlen = nlen - (domain-name); /* Is this a wildcard match? */ if ((dlen == cn->length-1) && !strncasecmp(domain, (char *) &cn->data[1], dlen)) { ret = LDAP_SUCCESS; } } } if( ret == LDAP_LOCAL_ERROR ) { Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " "common name in certificate (%.*s).\n", name, cn->length, cn->data ); ret = LDAP_CONNECT_ERROR; if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( _("TLS: hostname does not match CN in peer certificate")); } } X509_free(x); return ret; }