prefer key from authenticated slot, allow certificate name with token

Resolves TLS failures in replication in 389 Directory Server introduced
by recent Mozilla NSS backend fixes.
This commit is contained in:
Jan Vcelak 2012-08-13 15:33:35 +02:00
parent bfe48e26db
commit ad070fca8d
3 changed files with 138 additions and 1 deletions

View File

@ -0,0 +1,47 @@
Accept nss certificate name in the form of tokenname:certnickname
Author: Rich Megginson <rmeggins@redhat.com>
Upstream ITS: #7360
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
index 5022efb..7377bb1 100644
--- a/libraries/libldap/tls_m.c
+++ b/libraries/libldap/tls_m.c
@@ -2102,6 +2102,22 @@ tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int 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 )
{
@@ -2268,7 +2284,10 @@ tlsm_deferred_ctx_init( void *arg )
} else {
char *tmp_certname;
- if (ctx->tc_certdb_slot) {
+ 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);
--
1.7.11.4

View File

@ -0,0 +1,81 @@
MozNSS: prefer authenticated slot when getting private key
Author: Jan Vcelak <jvcelak@redhat.com>
Upstream ITS: #7359
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
index f37da06..5022efb 100644
--- a/libraries/libldap/tls_m.c
+++ b/libraries/libldap/tls_m.c
@@ -901,7 +901,7 @@ 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)
return NULL;
@@ -990,6 +990,38 @@ 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 && !result; le = le->next) {
+ PK11SlotInfo *slot = le->slot;
+ if (!PK11_IsLoggedIn(slot, NULL))
+ continue;
+
+ result = PK11_FindKeyByDERCert(slot, ctx->tc_certificate, pin_arg);
+ }
+
+ PK11_FreeSlotList(slots);
+ return result;
+}
+
static SECStatus
tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only,
@@ -1303,7 +1335,19 @@ tlsm_ctx_load_private_key(tlsm_ctx *ctx)
void *pin_arg = SSL_RevealPinArg(ctx->tc_model);
- ctx->tc_private_key = PK11_FindKeyByAnyCert(ctx->tc_certificate, pin_arg);
+ 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);
+
+ /* 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,
--
1.7.11.4

View File

@ -8,7 +8,7 @@
Name: openldap
Version: 2.4.32
Release: 1%{?dist}
Release: 2%{?dist}
Summary: LDAP support libraries
Group: System Environment/Daemons
License: OpenLDAP
@ -40,6 +40,8 @@ Patch8: openldap-syncrepl-unset-tls-options.patch
Patch9: openldap-constraint-count.patch
Patch10: openldap-man-sasl-nocanon.patch
Patch11: openldap-ai-addrconfig.patch
Patch12: openldap-nss-prefer-unlocked-key.patch
Patch13: openldap-nss-allow-certname-with-token-name.patch
# Fedora specific patches
Patch100: openldap-autoconf-pkgconfig-nss.patch
@ -153,6 +155,8 @@ ln -s %{_includedir}/nspr4 include/nspr
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch101 -p1
@ -610,6 +614,11 @@ exit 0
%{evolution_connector_prefix}/
%changelog
* Mon Aug 20 2012 Jan Vcelak <jvcelak@redhat.com> 2.4.32-2
- enhancement: TLS, prefer private keys from authenticated slots
- enhancement: TLS, allow certificate specification including token name
- resolve TLS failures in replication in 389 Directory Server
* Wed Aug 01 2012 Jan Vcelak <jvcelak@redhat.com> 2.4.32-1
- new upstream release
+ library: double free, SASL handling