X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ftls2.c;h=3809e9d8862f19a4df8bb346ccc2e0655c2f169a;hb=e57fa5f7ab8da9b95d5a6ef06d71bd0d70618011;hp=baadb1375d3901a2f7753a576ddd4924f4605eff;hpb=5b34dfcbf69a00bc002cf1f0f3acad91062ebc3f;p=openldap diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c index baadb1375d..3809e9d886 100644 --- a/libraries/libldap/tls2.c +++ b/libraries/libldap/tls2.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2009 The OpenLDAP Foundation. + * Copyright 1998-2012 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,10 +37,6 @@ #include "ldap-tls.h" -#ifdef LDAP_R_COMPILE -#include -#endif - static tls_impl *tls_imp = &ldap_int_tls_impl; #define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ (void *)tls_imp->ti_sbio ) @@ -143,7 +139,6 @@ void ldap_pvt_tls_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); - int i; ldap_int_tls_destroy( lo ); @@ -179,8 +174,6 @@ tls_init(tls_impl *impl ) int ldap_pvt_tls_init( void ) { - struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); - return tls_init( tls_imp ); } @@ -190,7 +183,7 @@ ldap_pvt_tls_init( void ) static int ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) { - int i, rc = 0; + int rc = 0; tls_impl *ti = tls_imp; struct ldaptls lts = lo->ldo_tls_info; @@ -272,13 +265,9 @@ ldap_pvt_tls_init_def_ctx( int is_server ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); int rc; -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex ); -#endif + LDAP_MUTEX_LOCK( &tls_def_ctx_mutex ); rc = ldap_int_tls_init_ctx( lo, is_server ); -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); -#endif + LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex ); return rc; } @@ -379,7 +368,7 @@ ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) return 1; } - msg = tls_imp->ti_session_errmsg( err, buf, sizeof(buf) ); + msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); if ( msg ) { if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); @@ -437,11 +426,14 @@ ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) if ( err < 0 ) { - char buf[256]; if ( update_flags( sb, ssl, err )) return 1; - Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n", - tls_imp->ti_session_errmsg( err, buf, sizeof(buf) ),0,0 ); + if ( DebugTest( LDAP_DEBUG_ANY ) ) { + char buf[256], *msg; + msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); + Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n", + msg ? msg : "(unknown)", 0, 0 ); + } ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT ); @@ -562,6 +554,7 @@ ldap_int_tls_config( LDAP *ld, int option, const char *arg ) } return ldap_pvt_tls_set_option( ld, option, &i ); } +#ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ i = -1; if ( strcasecmp( arg, "none" ) == 0 ) { @@ -575,6 +568,7 @@ ldap_int_tls_config( LDAP *ld, int option, const char *arg ) return ldap_pvt_tls_set_option( ld, option, &i ); } return -1; +#endif } return -1; } @@ -584,6 +578,11 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) { struct ldapoptions *lo; + if( option == LDAP_OPT_X_TLS_PACKAGE ) { + *(char **)arg = LDAP_STRDUP( tls_imp->ti_name ); + return 0; + } + if( ld != NULL ) { assert( LDAP_VALID( ld ) ); @@ -638,9 +637,11 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) case LDAP_OPT_X_TLS_REQUIRE_CERT: *(int *)arg = lo->ldo_tls_require_cert; break; +#ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ *(int *)arg = lo->ldo_tls_crlcheck; break; +#endif case LDAP_OPT_X_TLS_CIPHER_SUITE: *(char **)arg = lo->ldo_tls_ciphersuite ? LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; @@ -648,7 +649,7 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) case LDAP_OPT_X_TLS_PROTOCOL_MIN: *(int *)arg = lo->ldo_tls_protocol_min; break; - case LDAP_OPT_X_TLS_RANDOM_FILE: /* OpenSSL only */ + case LDAP_OPT_X_TLS_RANDOM_FILE: *(char **)arg = lo->ldo_tls_randfile ? LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; break; @@ -764,6 +765,7 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) return 0; } return -1; +#ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ if ( !arg ) return -1; switch( *(int *) arg ) { @@ -774,6 +776,7 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) return 0; } return -1; +#endif case LDAP_OPT_X_TLS_CIPHER_SUITE: if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; @@ -783,14 +786,12 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) if ( !arg ) return -1; lo->ldo_tls_protocol_min = *(int *)arg; return 0; - - case LDAP_OPT_X_TLS_RANDOM_FILE: /* OpenSSL only */ + case LDAP_OPT_X_TLS_RANDOM_FILE: if ( ld != NULL ) return -1; if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile ); lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; - case LDAP_OPT_X_TLS_NEWCTX: if ( !arg ) return -1; if ( lo->ldo_tls_ctx ) @@ -806,10 +807,14 @@ ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) int ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) { - Sockbuf *sb = conn->lconn_sb; + Sockbuf *sb; char *host; void *ssl; + if ( !conn ) + return LDAP_PARAM_ERROR; + + sb = conn->lconn_sb; if( srv ) { host = srv->lud_host; } else { @@ -837,7 +842,8 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) /* * compare host with name(s) in certificate */ - if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER) { + if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && + ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host ); if (ld->ld_errno != LDAP_SUCCESS) { return ld->ld_errno; @@ -871,8 +877,9 @@ ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, struct berval der_dn; int rc; - tls_imp->ti_session_my_dn( session, &der_dn ); - rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags ); + rc = tls_imp->ti_session_my_dn( session, &der_dn ); + if ( rc == LDAP_SUCCESS ) + rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags ); return rc; } #endif /* HAVE_TLS */ @@ -970,6 +977,93 @@ find_oid( struct berval *oid ) return NULL; } +/* Converts BER Bitstring value to LDAP BitString value (RFC4517) + * + * berValue : IN + * rfc4517Value: OUT + * + * berValue and ldapValue should not be NULL + */ + +#define BITS_PER_BYTE 8 +#define SQUOTE_LENGTH 1 +#define B_CHAR_LENGTH 1 +#define STR_OVERHEAD (2*SQUOTE_LENGTH + B_CHAR_LENGTH) + +static int +der_to_ldap_BitString (struct berval *berValue, + struct berval *ldapValue) +{ + ber_len_t bitPadding=0; + ber_len_t bits, maxBits; + char *tmpStr; + unsigned char byte; + ber_len_t bitLength; + ber_len_t valLen; + unsigned char* valPtr; + + ldapValue->bv_len=0; + ldapValue->bv_val=NULL; + + /* Gets padding and points to binary data */ + valLen=berValue->bv_len; + valPtr=(unsigned char*)berValue->bv_val; + if (valLen) { + bitPadding=(ber_len_t)(valPtr[0]); + valLen--; + valPtr++; + } + /* If Block is non DER encoding fixes to DER encoding */ + if (bitPadding >= BITS_PER_BYTE) { + if (valLen*BITS_PER_BYTE > bitPadding ) { + valLen-=(bitPadding/BITS_PER_BYTE); + bitPadding%=BITS_PER_BYTE; + } else { + valLen=0; + bitPadding=0; + } + } + /* Just in case bad encoding */ + if (valLen*BITS_PER_BYTE < bitPadding ) { + bitPadding=0; + valLen=0; + } + + /* Gets buffer to hold RFC4517 Bit String format */ + bitLength=valLen*BITS_PER_BYTE-bitPadding; + tmpStr=LDAP_MALLOC(bitLength + STR_OVERHEAD + 1); + + if (!tmpStr) + return LDAP_NO_MEMORY; + + ldapValue->bv_val=tmpStr; + ldapValue->bv_len=bitLength + STR_OVERHEAD; + + /* Formatting in '*binary-digit'B format */ + maxBits=BITS_PER_BYTE; + *tmpStr++ ='\''; + while(valLen) { + byte=*valPtr; + if (valLen==1) + maxBits-=bitPadding; + for (bits=0; bitsla_attr = oidname->name; } } + newAVA->la_private = NULL; + newAVA->la_flags = LDAP_AVA_STRING; tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM ); switch(tag) { case LBER_TAG_UNIVERSAL: @@ -1124,22 +1220,29 @@ ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func, /* This uses 8-bit, assume ISO 8859-1 */ csize = 1; to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value ); + newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; +allocd: newAVA->la_flags |= LDAP_AVA_FREE_VALUE; if (rc != LDAP_SUCCESS) goto nomem; - newAVA->la_flags = LDAP_AVA_NONPRINTABLE; break; case LBER_TAG_UTF8: - newAVA->la_flags = LDAP_AVA_NONPRINTABLE; + newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; /* This is already in UTF-8 encoding */ case LBER_TAG_IA5: case LBER_TAG_PRINTABLE: /* These are always 7-bit strings */ newAVA->la_value = Val; + break; + case LBER_BITSTRING: + /* X.690 bitString value converted to RFC4517 Bit String */ + rc = der_to_ldap_BitString( &Val, &newAVA->la_value ); + goto allocd; default: - ; + /* Not a string type at all */ + newAVA->la_flags = 0; + newAVA->la_value = Val; + break; } - newAVA->la_private = NULL; - newAVA->la_flags = LDAP_AVA_STRING; newAVA++; } *newRDN++ = NULL;