X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=libraries%2Flibldap%2Ftls_m.c;h=a8691c59776cbe51658ab23bff17eb579549d80c;hb=e56a849e5d1ebde21092b9ff8a8cf4b9c5f8dfb6;hp=4b5727bd03361bbc77af46d3dbb9c4bb38aca42c;hpb=c6b5abbfd20567116846ebc38f0005c429284c98;p=openldap diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c index 4b5727bd03..a8691c5977 100644 --- a/libraries/libldap/tls_m.c +++ b/libraries/libldap/tls_m.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2008-2012 The OpenLDAP Foundation. + * Copyright 2008-2017 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -901,9 +901,9 @@ tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) * capability the server would have to be started in foreground mode * if using an encrypted key. */ - if ( ctx->tc_pin_file ) { + if ( ctx && ctx->tc_pin_file ) { pwdstr = tlsm_get_pin_from_file( token_name, ctx ); - if (retry && pwdstr != NULL) + if ( retry && pwdstr != NULL ) return NULL; } #endif /* RETRIEVE_PASSWORD_FROM_FILE */ @@ -912,6 +912,7 @@ tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) int infd = PR_FileDesc2NativeHandle( PR_STDIN ); int isTTY = isatty( infd ); unsigned char phrase[200]; + char *dummy; /* Prompt for password */ if ( isTTY ) { fprintf( stdout, @@ -919,7 +920,8 @@ tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx) token_name ? token_name : DEFAULT_TOKEN_NAME ); echoOff( infd ); } - fgets( (char*)phrase, sizeof(phrase), stdin ); + dummy = fgets( (char*)phrase, sizeof(phrase), stdin ); + (void) dummy; if ( isTTY ) { fprintf( stdout, "\n" ); echoOn( infd ); @@ -950,7 +952,7 @@ tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg) static char * tlsm_ctx_subject_name(tlsm_ctx *ctx) { - if (!ctx || !ctx->tc_certificate) + if ( !ctx || !ctx->tc_certificate ) return "(unknown)"; return ctx->tc_certificate->subjectName; @@ -990,16 +992,49 @@ tlsm_cert_is_self_issued( CERTCertificate *cert ) return is_self_issued; } +/* + * The private key for used certificate can be already unlocked by other + * thread or library. Find the unlocked key if possible. + */ +static SECKEYPrivateKey * +tlsm_find_unlocked_key( tlsm_ctx *ctx, void *pin_arg ) +{ + SECKEYPrivateKey *result = NULL; + + PK11SlotList *slots = PK11_GetAllSlotsForCert( ctx->tc_certificate, NULL ); + if ( !slots ) { + PRErrorCode errcode = PR_GetError(); + Debug( LDAP_DEBUG_ANY, + "TLS: cannot get all slots for certificate '%s' (error %d: %s)", + tlsm_ctx_subject_name( ctx ), errcode, + PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); + return result; + } + + PK11SlotListElement *le; + for ( le = slots->head; le; le = le->next ) { + PK11SlotInfo *slot = le->slot; + if ( PK11_IsLoggedIn( slot, NULL ) ) { + result = PK11_FindKeyByDERCert( slot, ctx->tc_certificate, pin_arg ); + break; + } + } + + PK11_FreeSlotList( slots ); + return result; +} + static SECStatus tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg, - PRBool checksig, SECCertificateUsage certUsage, int errorToIgnore ) + PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only, + PRBool ignore_issuer ) { CERTVerifyLog verifylog; SECStatus ret = SECSuccess; const char *name; int debug_level = LDAP_DEBUG_ANY; - if ( errorToIgnore == -1 ) { + if ( warn_only ) { debug_level = LDAP_DEBUG_TRACE; } @@ -1061,9 +1096,13 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg, name, 0, 0 ); } - PR_SetError(orig_error, orig_oserror); + PR_SetError( orig_error, orig_oserror ); - } else if ( errorToIgnore && ( node->error == errorToIgnore ) ) { + } else if ( warn_only || ( ignore_issuer && ( + node->error == SEC_ERROR_UNKNOWN_ISSUER || + node->error == SEC_ERROR_UNTRUSTED_ISSUER ) + ) ) { + ret = SECSuccess; Debug( debug_level, "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n", name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) ); @@ -1084,8 +1123,6 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg, if ( ret == SECSuccess ) { Debug( LDAP_DEBUG_TRACE, "TLS: certificate [%s] is valid\n", name, 0, 0 ); - } else if ( errorToIgnore == -1 ) { - ret = SECSuccess; } return ret; @@ -1098,15 +1135,11 @@ tlsm_auth_cert_handler(void *arg, PRFileDesc *fd, SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer; SECStatus ret = SECSuccess; CERTCertificate *peercert = SSL_PeerCertificate( fd ); - int errorToIgnore = 0; tlsm_ctx *ctx = (tlsm_ctx *)arg; - if (ctx && ctx->tc_warn_only ) - errorToIgnore = -1; - ret = tlsm_verify_cert( ctx->tc_certdb, peercert, SSL_RevealPinArg( fd ), - checksig, certUsage, errorToIgnore ); + checksig, certUsage, ctx->tc_warn_only, PR_FALSE ); CERT_DestroyCertificate( peercert ); return ret; @@ -1244,10 +1277,10 @@ tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca ) return -1; } - PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) ); - PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); - PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); - PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); + PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) ); + PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) ); + PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *) filename, strlen( filename ) + 1 ); + PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof( CK_BBOOL ) ); cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ ); @@ -1294,23 +1327,35 @@ tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca ) } static int -tlsm_ctx_load_private_key(tlsm_ctx *ctx) +tlsm_ctx_load_private_key( tlsm_ctx *ctx ) { - if (!ctx->tc_certificate) + if ( !ctx->tc_certificate ) return -1; - if (ctx->tc_private_key) + if ( ctx->tc_private_key ) return 0; - void *pin_arg = SSL_RevealPinArg(ctx->tc_model); + void *pin_arg = SSL_RevealPinArg( ctx->tc_model ); + + SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key( ctx, pin_arg ); + Debug( LDAP_DEBUG_ANY, + "TLS: %s unlocked certificate for certificate '%s'.\n", + unlocked_key ? "found" : "no", tlsm_ctx_subject_name( ctx ), 0 ); - ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg); - if (!ctx->tc_private_key) { + /* prefer unlocked key, then key from opened certdb, then any other */ + if ( unlocked_key ) + ctx->tc_private_key = unlocked_key; + else if ( ctx->tc_certdb_slot ) + ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg ); + else + ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg ); + + if ( !ctx->tc_private_key ) { PRErrorCode errcode = PR_GetError(); Debug(LDAP_DEBUG_ANY, "TLS: cannot find private key for certificate '%s' (error %d: %s)", - tlsm_ctx_subject_name(ctx), errcode, - PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT)); + tlsm_ctx_subject_name( ctx ), errcode, + PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); return -1; } @@ -1358,9 +1403,9 @@ tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename ) return -1; } - PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof(objClass) ); - PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); - PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); + PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) ); + PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) ); + PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen( filename ) + 1 ); key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ ); @@ -1548,28 +1593,28 @@ tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix ) * which is unique for each context. */ static PK11SlotInfo * -tlsm_init_open_certdb(tlsm_ctx *ctx, const char *dbdir, const char *prefix) +tlsm_init_open_certdb( tlsm_ctx *ctx, const char *dbdir, const char *prefix ) { PK11SlotInfo *slot = NULL; char *token_desc = NULL; char *config = NULL; - token_desc = PR_smprintf(TLSM_CERTDB_DESC_FMT, ctx->tc_unique); - config = PR_smprintf("configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly", - dbdir, token_desc, prefix, prefix); - Debug(LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0); + token_desc = PR_smprintf( TLSM_CERTDB_DESC_FMT, ctx->tc_unique ); + config = PR_smprintf( "configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly", + dbdir, token_desc, prefix, prefix ); + Debug( LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0 ); - slot = SECMOD_OpenUserDB(config); - if (!slot) { + slot = SECMOD_OpenUserDB( config ); + if ( !slot ) { PRErrorCode errcode = PR_GetError(); - Debug(LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode, - PR_ErrorToString(errcode, PR_LANGUAGE_I_DEFAULT)); + Debug( LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode, + PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) ); } - if (token_desc) - PR_smprintf_free(token_desc); - if (config) - PR_smprintf_free(config); + if ( token_desc ) + PR_smprintf_free( token_desc ); + if ( config ) + PR_smprintf_free( config ); return slot; } @@ -1596,6 +1641,8 @@ tlsm_deferred_init( void *arg ) NSSInitContext *initctx = NULL; PK11SlotInfo *certdb_slot = NULL; #endif + SSLVersionRange range; + SSLProtocolVariant variant; SECStatus rc; int done = 0; @@ -1671,14 +1718,14 @@ tlsm_deferred_init( void *arg ) #endif rc = SECFailure; - if (initctx != NULL) { - certdb_slot = tlsm_init_open_certdb(ctx, realcertdir, prefix); - if (certdb_slot) { + if ( initctx != NULL ) { + certdb_slot = tlsm_init_open_certdb( ctx, realcertdir, prefix ); + if ( certdb_slot ) { rc = SECSuccess; ctx->tc_initctx = initctx; ctx->tc_certdb_slot = certdb_slot; } else { - NSS_ShutdownContext(initctx); + NSS_ShutdownContext( initctx ); initctx = NULL; } } @@ -1722,7 +1769,7 @@ tlsm_deferred_init( void *arg ) #else initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB, &initParams, flags ); - if (initctx) { + if ( initctx ) { ctx->tc_initctx = initctx; rc = SECSuccess; } else { @@ -1780,6 +1827,16 @@ tlsm_deferred_init( void *arg ) ctx->tc_using_pem = PR_TRUE; } + /* + * Set the SSL version range. MozNSS SSL versions are the same as openldap's: + * + * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_* + */ + SSL_VersionRangeGetSupported(ssl_variant_stream, &range); /* this sets the max */ + range.min = lt->lt_protocol_min ? lt->lt_protocol_min : range.min; + variant = ssl_variant_stream; + SSL_VersionRangeSetDefault(variant, &range); + NSS_SetDomesticPolicy(); PK11_SetPasswordFunc( tlsm_pin_prompt ); @@ -1810,27 +1867,22 @@ tlsm_deferred_init( void *arg ) * The key is loaded and stored in ctx->tc_private_key */ static int -tlsm_find_and_verify_cert_key(tlsm_ctx *ctx) +tlsm_find_and_verify_cert_key( tlsm_ctx *ctx ) { SECCertificateUsage certUsage; PRBool checkSig; SECStatus status; - int errorToIgnore; void *pin_arg; - if (tlsm_ctx_load_private_key(ctx)) + if ( tlsm_ctx_load_private_key( ctx ) ) return -1; - pin_arg = SSL_RevealPinArg(ctx->tc_model); + pin_arg = SSL_RevealPinArg( ctx->tc_model ); certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient; checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE; - if ( ctx->tc_warn_only ) - errorToIgnore = -1; - else - errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER; /* may not have a CA cert */ status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg, - checkSig, certUsage, errorToIgnore ); + checkSig, certUsage, ctx->tc_warn_only, PR_TRUE ); return status == SECSuccess ? 0 : -1; } @@ -1842,11 +1894,11 @@ tlsm_get_client_auth_data( void *arg, PRFileDesc *fd, { tlsm_ctx *ctx = (tlsm_ctx *)arg; - if (pRetCert) - *pRetCert = CERT_DupCertificate(ctx->tc_certificate); + if ( pRetCert ) + *pRetCert = CERT_DupCertificate( ctx->tc_certificate ); - if (pRetKey) - *pRetKey = SECKEY_CopyPrivateKey(ctx->tc_private_key); + if ( pRetKey ) + *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key ); return SECSuccess; } @@ -1897,30 +1949,30 @@ tlsm_copy_config ( const struct ldaptls *config ) { struct ldaptls *copy; - assert(config); + assert( config ); - copy = LDAP_MALLOC(sizeof(*copy)); - if (!copy) + copy = LDAP_MALLOC( sizeof( *copy ) ); + if ( !copy ) return NULL; - memset(copy, 0, sizeof(*copy)); - - if (config->lt_certfile) - copy->lt_certfile = LDAP_STRDUP(config->lt_certfile); - if (config->lt_keyfile) - copy->lt_keyfile = LDAP_STRDUP(config->lt_keyfile); - if (config->lt_dhfile) - copy->lt_dhfile = LDAP_STRDUP(config->lt_dhfile); - if (config->lt_cacertfile) - copy->lt_cacertfile = LDAP_STRDUP(config->lt_cacertfile); - if (config->lt_cacertdir) - copy->lt_cacertdir = LDAP_STRDUP(config->lt_cacertdir); - if (config->lt_ciphersuite) - copy->lt_ciphersuite = LDAP_STRDUP(config->lt_ciphersuite); - if (config->lt_crlfile) - copy->lt_crlfile = LDAP_STRDUP(config->lt_crlfile); - if (config->lt_randfile) - copy->lt_randfile = LDAP_STRDUP(config->lt_randfile); + memset( copy, 0, sizeof( *copy ) ); + + if ( config->lt_certfile ) + copy->lt_certfile = LDAP_STRDUP( config->lt_certfile ); + if ( config->lt_keyfile ) + copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile ); + if ( config->lt_dhfile ) + copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile ); + if ( config->lt_cacertfile ) + copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile ); + if ( config->lt_cacertdir ) + copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir ); + if ( config->lt_ciphersuite ) + copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite ); + if ( config->lt_crlfile ) + copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile ); + if ( config->lt_randfile ) + copy->lt_randfile = LDAP_STRDUP( config->lt_randfile ); copy->lt_protocol_min = config->lt_protocol_min; @@ -1930,26 +1982,26 @@ tlsm_copy_config ( const struct ldaptls *config ) static void tlsm_free_config ( struct ldaptls *config ) { - assert(config); + assert( config ); - if (config->lt_certfile) - LDAP_FREE(config->lt_certfile); - if (config->lt_keyfile) - LDAP_FREE(config->lt_keyfile); - if (config->lt_dhfile) - LDAP_FREE(config->lt_dhfile); - if (config->lt_cacertfile) - LDAP_FREE(config->lt_cacertfile); - if (config->lt_cacertdir) - LDAP_FREE(config->lt_cacertdir); - if (config->lt_ciphersuite) - LDAP_FREE(config->lt_ciphersuite); - if (config->lt_crlfile) - LDAP_FREE(config->lt_crlfile); - if (config->lt_randfile) - LDAP_FREE(config->lt_randfile); + if ( config->lt_certfile ) + LDAP_FREE( config->lt_certfile ); + if ( config->lt_keyfile ) + LDAP_FREE( config->lt_keyfile ); + if ( config->lt_dhfile ) + LDAP_FREE( config->lt_dhfile ); + if ( config->lt_cacertfile ) + LDAP_FREE( config->lt_cacertfile ); + if ( config->lt_cacertdir ) + LDAP_FREE( config->lt_cacertdir ); + if ( config->lt_ciphersuite ) + LDAP_FREE( config->lt_ciphersuite ); + if ( config->lt_crlfile ) + LDAP_FREE( config->lt_crlfile ); + if ( config->lt_randfile ) + LDAP_FREE( config->lt_randfile ); - LDAP_FREE(config); + LDAP_FREE( config ); } static tls_ctx * @@ -2013,10 +2065,10 @@ tlsm_ctx_free ( tls_ctx *ctx ) LDAP_MUTEX_LOCK( &tlsm_init_mutex ); if ( c->tc_model ) PR_Close( c->tc_model ); - if (c->tc_certificate) - CERT_DestroyCertificate(c->tc_certificate); - if (c->tc_private_key) - SECKEY_DestroyPrivateKey(c->tc_private_key); + if ( c->tc_certificate ) + CERT_DestroyCertificate( c->tc_certificate ); + if ( c->tc_private_key ) + SECKEY_DestroyPrivateKey( c->tc_private_key ); c->tc_certdb = NULL; /* if not the default, may have to clean up */ if ( c->tc_certdb_slot ) { if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) { @@ -2026,8 +2078,10 @@ tlsm_ctx_free ( tls_ctx *ctx ) errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ); } } - PL_strfree( c->tc_pin_file ); - c->tc_pin_file = NULL; + if ( c->tc_pin_file ) { + PL_strfree( c->tc_pin_file ); + c->tc_pin_file = NULL; + } tlsm_free_pem_objs( c ); #ifdef HAVE_NSS_INITCONTEXT if ( c->tc_initctx ) { @@ -2058,12 +2112,28 @@ static int tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx; - ctx->tc_config = tlsm_copy_config(lt); + ctx->tc_config = tlsm_copy_config( lt ); ctx->tc_is_server = is_server; return 0; } +/* returns true if the given string looks like + "tokenname" ":" "certnickname" + This is true if there is a ':' colon character + in the string and the colon is not the first + or the last character in the string +*/ +static int +tlsm_is_tokenname_certnick( const char *certfile ) +{ + if ( certfile ) { + const char *ptr = PL_strchr( certfile, ':' ); + return ptr && (ptr != certfile) && (*(ptr+1)); + } + return 0; +} + static int tlsm_deferred_ctx_init( void *arg ) { @@ -2230,16 +2300,19 @@ tlsm_deferred_ctx_init( void *arg ) } else { char *tmp_certname; - if (ctx->tc_certdb_slot) { - tmp_certname = PR_smprintf(TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile); + if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) { + /* assume already in form tokenname:certnickname */ + tmp_certname = PL_strdup( lt->lt_certfile ); + } else if ( ctx->tc_certdb_slot ) { + tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile ); } else { - tmp_certname = PR_smprintf("%s", lt->lt_certfile); + tmp_certname = PR_smprintf( "%s", lt->lt_certfile ); } - ctx->tc_certificate = PK11_FindCertFromNickname(tmp_certname, SSL_RevealPinArg(ctx->tc_model)); - PR_smprintf_free(tmp_certname); + ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) ); + PR_smprintf_free( tmp_certname ); - if (!ctx->tc_certificate) { + if ( !ctx->tc_certificate ) { PRErrorCode errcode = PR_GetError(); Debug( LDAP_DEBUG_ANY, "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n", @@ -2258,7 +2331,8 @@ tlsm_deferred_ctx_init( void *arg ) return rc; } } else { - PL_strfree( ctx->tc_pin_file ); + if ( ctx->tc_pin_file ) + PL_strfree( ctx->tc_pin_file ); ctx->tc_pin_file = PL_strdup( lt->lt_keyfile ); } } @@ -2304,7 +2378,7 @@ tlsm_deferred_ctx_init( void *arg ) return -1; } - if (tlsm_find_and_verify_cert_key(ctx)) { + if ( tlsm_find_and_verify_cert_key( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: error: unable to find and verify server's cert and key for certificate %s\n", tlsm_ctx_subject_name(ctx), 0, 0 ); @@ -2781,6 +2855,79 @@ tlsm_session_strength( tls_session *session ) return rc ? 0 : keySize; } +static int +tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server) +{ + /* Need upstream support https://bugzilla.mozilla.org/show_bug.cgi?id=563276 */ + return 0; +} + +/* + * Yet again, we're pasting in glue that MozNSS ought to provide itself. + * + * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_* + */ +static struct { + const char *name; + int num; +} pvers[] = { + { "SSLv2", SSL_LIBRARY_VERSION_2 }, + { "SSLv3", SSL_LIBRARY_VERSION_3_0 }, + { "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 }, + { "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 }, + { "TLSv1.2", SSL_LIBRARY_VERSION_TLS_1_2 }, + { "TLSv1.3", SSL_LIBRARY_VERSION_TLS_1_3 }, + { NULL, 0 } +}; + +static const char * +tlsm_session_version( tls_session *sess ) +{ + tlsm_session *s = (tlsm_session *)sess; + SSLChannelInfo info; + int rc; + rc = SSL_GetChannelInfo( s, &info, sizeof( info )); + if ( rc == 0 ) { + int i; + for (i=0; pvers[i].name; i++) + if (pvers[i].num == info.protocolVersion) + return pvers[i].name; + } + return "unknown"; +} + +static const char * +tlsm_session_cipher( tls_session *sess ) +{ + tlsm_session *s = (tlsm_session *)sess; + SSLChannelInfo info; + int rc; + rc = SSL_GetChannelInfo( s, &info, sizeof( info )); + if ( rc == 0 ) { + SSLCipherSuiteInfo csinfo; + rc = SSL_GetCipherSuiteInfo( info.cipherSuite, &csinfo, sizeof( csinfo )); + if ( rc == 0 ) + return csinfo.cipherSuiteName; + } + return "unknown"; +} + +static int +tlsm_session_peercert( tls_session *sess, struct berval *der ) +{ + tlsm_session *s = (tlsm_session *)sess; + CERTCertificate *cert; + cert = SSL_PeerCertificate( s ); + if (!cert) + return -1; + der->bv_len = cert->derCert.len; + der->bv_val = LDAP_MALLOC( der->bv_len ); + if (!der->bv_val) + return -1; + memcpy( der->bv_val, cert->derCert.data, der->bv_len ); + return 0; +} + /* * TLS support for LBER Sockbufs */ @@ -3209,6 +3356,10 @@ tls_impl ldap_int_tls_impl = { tlsm_session_peer_dn, tlsm_session_chkhost, tlsm_session_strength, + tlsm_session_unique, + tlsm_session_version, + tlsm_session_cipher, + tlsm_session_peercert, &tlsm_sbio,