version 1.8, 2009/07/01 21:46:36
|
version 1.11, 2009/08/07 19:46:25
|
Line 1
|
Line 1
|
/* tls_o.c - Handle tls/ssl using OpenSSL */ |
/* tls_o.c - Handle tls/ssl using OpenSSL */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/tls_o.c,v 1.7 2009/03/02 16:43:38 hyc Exp $ */ |
/* $OpenLDAP: pkg/ldap/libraries/libldap/tls_o.c,v 1.10 2009/08/07 09:59:42 hyc Exp $ */ |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
* |
* |
* Copyright 2008-2009 The OpenLDAP Foundation. |
* Copyright 2008-2009 The OpenLDAP Foundation. |
Line 466 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 466 tlso_session_chkhost( LDAP *ld, tls_sess
|
X509 *x; |
X509 *x; |
const char *name; |
const char *name; |
char *ptr; |
char *ptr; |
int ntype = IS_DNS; |
int ntype = IS_DNS, nlen; |
#ifdef LDAP_PF_INET6 |
#ifdef LDAP_PF_INET6 |
struct in6_addr addr; |
struct in6_addr addr; |
#else |
#else |
Line 480 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 480 tlso_session_chkhost( LDAP *ld, tls_sess
|
} else { |
} else { |
name = name_in; |
name = name_in; |
} |
} |
|
nlen = strlen(name); |
|
|
x = tlso_get_cert(s); |
x = tlso_get_cert(s); |
if (!x) { |
if (!x) { |
Line 513 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 514 tlso_session_chkhost( LDAP *ld, tls_sess
|
ex = X509_get_ext(x, i); |
ex = X509_get_ext(x, i); |
alt = X509V3_EXT_d2i(ex); |
alt = X509V3_EXT_d2i(ex); |
if (alt) { |
if (alt) { |
int n, len1 = 0, len2 = 0; |
int n, len2 = 0; |
char *domain = NULL; |
char *domain = NULL; |
GENERAL_NAME *gn; |
GENERAL_NAME *gn; |
|
|
if (ntype == IS_DNS) { |
if (ntype == IS_DNS) { |
len1 = strlen(name); |
|
domain = strchr(name, '.'); |
domain = strchr(name, '.'); |
if (domain) { |
if (domain) { |
len2 = len1 - (domain-name); |
len2 = nlen - (domain-name); |
} |
} |
} |
} |
n = sk_GENERAL_NAME_num(alt); |
n = sk_GENERAL_NAME_num(alt); |
Line 539 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 539 tlso_session_chkhost( LDAP *ld, tls_sess
|
if (sl == 0) continue; |
if (sl == 0) continue; |
|
|
/* Is this an exact match? */ |
/* Is this an exact match? */ |
if ((len1 == sl) && !strncasecmp(name, sn, len1)) { |
if ((nlen == sl) && !strncasecmp(name, sn, nlen)) { |
break; |
break; |
} |
} |
|
|
Line 579 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 579 tlso_session_chkhost( LDAP *ld, tls_sess
|
|
|
if (ret != LDAP_SUCCESS) { |
if (ret != LDAP_SUCCESS) { |
X509_NAME *xn; |
X509_NAME *xn; |
char buf[2048]; |
X509_NAME_ENTRY *ne; |
buf[0] = '\0'; |
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); |
xn = X509_get_subject_name(x); |
if( X509_NAME_get_text_by_NID( xn, NID_commonName, |
navas = X509_NAME_entry_count( xn ); |
buf, sizeof(buf)) == -1) |
for ( i=navas-1; i>=0; i-- ) { |
|
ne = X509_NAME_get_entry( xn, i ); |
|
if ( !OBJ_cmp( ne->object, obj )) { |
|
cn = X509_NAME_ENTRY_get_data( ne ); |
|
break; |
|
} |
|
} |
|
|
|
if( !cn ) |
{ |
{ |
|
no_cn: |
Debug( LDAP_DEBUG_ANY, |
Debug( LDAP_DEBUG_ANY, |
"TLS: unable to get common name from peer certificate.\n", |
"TLS: unable to get common name from peer certificate.\n", |
0, 0, 0 ); |
0, 0, 0 ); |
Line 596 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 611 tlso_session_chkhost( LDAP *ld, tls_sess
|
ld->ld_error = LDAP_STRDUP( |
ld->ld_error = LDAP_STRDUP( |
_("TLS: unable to get CN from peer certificate")); |
_("TLS: unable to get CN from peer certificate")); |
|
|
} else if (strcasecmp(name, buf) == 0 ) { |
} else if ( cn->length == nlen && |
|
strncasecmp( name, (char *) cn->data, nlen ) == 0 ) { |
ret = LDAP_SUCCESS; |
ret = LDAP_SUCCESS; |
|
|
} else if (( buf[0] == '*' ) && ( buf[1] == '.' )) { |
} else if (( cn->data[0] == '*' ) && ( cn->data[1] == '.' )) { |
char *domain = strchr(name, '.'); |
char *domain = strchr(name, '.'); |
if( domain ) { |
if( domain ) { |
size_t dlen = 0; |
size_t dlen; |
size_t sl; |
|
|
|
sl = strlen(name); |
dlen = nlen - (domain-name); |
dlen = sl - (domain-name); |
|
sl = strlen(buf); |
|
|
|
/* Is this a wildcard match? */ |
/* Is this a wildcard match? */ |
if ((dlen == sl-1) && !strncasecmp(domain, &buf[1], dlen)) { |
if ((dlen == cn->length-1) && |
|
!strncasecmp(domain, (char *) &cn->data[1], dlen)) { |
ret = LDAP_SUCCESS; |
ret = LDAP_SUCCESS; |
} |
} |
} |
} |
Line 618 tlso_session_chkhost( LDAP *ld, tls_sess
|
Line 632 tlso_session_chkhost( LDAP *ld, tls_sess
|
|
|
if( ret == LDAP_LOCAL_ERROR ) { |
if( ret == LDAP_LOCAL_ERROR ) { |
Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " |
Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match " |
"common name in certificate (%s).\n", |
"common name in certificate (%.*s).\n", |
name, buf, 0 ); |
name, cn->length, cn->data ); |
ret = LDAP_CONNECT_ERROR; |
ret = LDAP_CONNECT_ERROR; |
if ( ld->ld_error ) { |
if ( ld->ld_error ) { |
LDAP_FREE( ld->ld_error ); |
LDAP_FREE( ld->ld_error ); |