221 lines
6.4 KiB
Diff
221 lines
6.4 KiB
Diff
|
NOTE: The patch has been adjusted to match the base code before backporting.
|
||
|
|
||
|
From 16f8b0902c28b1eaab93ddf120ce40b89bcda8d1 Mon Sep 17 00:00:00 2001
|
||
|
From: Howard Chu <hyc@openldap.org>
|
||
|
Date: Tue, 10 Sep 2013 04:26:51 -0700
|
||
|
Subject: [PATCH] ITS#7398 add LDAP_OPT_X_TLS_PEERCERT
|
||
|
|
||
|
retrieve peer cert for an active TLS session
|
||
|
---
|
||
|
doc/man/man3/ldap_get_option.3 | 8 ++++++++
|
||
|
include/ldap.h | 1 +
|
||
|
libraries/libldap/ldap-tls.h | 2 ++
|
||
|
libraries/libldap/tls2.c | 24 ++++++++++++++++++++++++
|
||
|
libraries/libldap/tls_g.c | 19 +++++++++++++++++++
|
||
|
libraries/libldap/tls_m.c | 17 +++++++++++++++++
|
||
|
libraries/libldap/tls_o.c | 16 ++++++++++++++++
|
||
|
7 files changed, 87 insertions(+)
|
||
|
|
||
|
diff --git a/doc/man/man3/ldap_get_option.3 b/doc/man/man3/ldap_get_option.3
|
||
|
index eb3f25b33..7546875f5 100644
|
||
|
--- a/doc/man/man3/ldap_get_option.3
|
||
|
+++ b/doc/man/man3/ldap_get_option.3
|
||
|
@@ -744,6 +744,14 @@ A non-zero value pointed to by
|
||
|
.BR invalue
|
||
|
tells the library to create a context for a server.
|
||
|
.TP
|
||
|
+.B LDAP_OPT_X_TLS_PEERCERT
|
||
|
+Gets the peer's certificate in DER format from an established TLS session.
|
||
|
+.BR outvalue
|
||
|
+must be
|
||
|
+.BR "struct berval *" ,
|
||
|
+and the data it returns needs to be freed by the caller using
|
||
|
+.BR ldap_memfree (3).
|
||
|
+.TP
|
||
|
.B LDAP_OPT_X_TLS_PROTOCOL_MIN
|
||
|
Sets/gets the minimum protocol version.
|
||
|
.BR invalue
|
||
|
diff --git a/include/ldap.h b/include/ldap.h
|
||
|
index 389441031..88bfcabf8 100644
|
||
|
--- a/include/ldap.h
|
||
|
+++ b/include/ldap.h
|
||
|
@@ -160,6 +160,7 @@ LDAP_BEGIN_DECL
|
||
|
#define LDAP_OPT_X_TLS_PACKAGE 0x6011
|
||
|
#define LDAP_OPT_X_TLS_ECNAME 0x6012
|
||
|
#define LDAP_OPT_X_TLS_REQUIRE_SAN 0x601a
|
||
|
+#define LDAP_OPT_X_TLS_PEERCERT 0x6015 /* read-only */
|
||
|
|
||
|
#define LDAP_OPT_X_TLS_NEVER 0
|
||
|
#define LDAP_OPT_X_TLS_HARD 1
|
||
|
diff --git a/libraries/libldap/ldap-tls.h b/libraries/libldap/ldap-tls.h
|
||
|
index 0ecf81ab9..103004fa7 100644
|
||
|
--- a/libraries/libldap/ldap-tls.h
|
||
|
+++ b/libraries/libldap/ldap-tls.h
|
||
|
@@ -42,6 +42,7 @@ typedef int (TI_session_dn)(tls_session *sess, struct berval *dn);
|
||
|
typedef int (TI_session_chkhost)(LDAP *ld, tls_session *s, const char *name_in);
|
||
|
typedef int (TI_session_strength)(tls_session *sess);
|
||
|
typedef int (TI_session_unique)(tls_session *sess, struct berval *buf, int is_server);
|
||
|
+typedef int (TI_session_peercert)(tls_session *s, struct berval *der);
|
||
|
|
||
|
typedef void (TI_thr_init)(void);
|
||
|
|
||
|
@@ -66,6 +67,7 @@ typedef struct tls_impl {
|
||
|
TI_session_chkhost *ti_session_chkhost;
|
||
|
TI_session_strength *ti_session_strength;
|
||
|
TI_session_unique *ti_session_unique;
|
||
|
+ TI_session_peercert *ti_session_peercert;
|
||
|
|
||
|
Sockbuf_IO *ti_sbio;
|
||
|
|
||
|
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
|
||
|
index 13d734362..ad09ba39b 100644
|
||
|
--- a/libraries/libldap/tls2.c
|
||
|
+++ b/libraries/libldap/tls2.c
|
||
|
@@ -705,6 +705,23 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
|
||
|
case LDAP_OPT_X_TLS_CONNECT_ARG:
|
||
|
*(void **)arg = lo->ldo_tls_connect_arg;
|
||
|
break;
|
||
|
+ case LDAP_OPT_X_TLS_PEERCERT: {
|
||
|
+ void *sess = NULL;
|
||
|
+ struct berval *bv = arg;
|
||
|
+ bv->bv_len = 0;
|
||
|
+ bv->bv_val = NULL;
|
||
|
+ if ( ld != NULL ) {
|
||
|
+ LDAPConn *conn = ld->ld_defconn;
|
||
|
+ if ( conn != NULL ) {
|
||
|
+ Sockbuf *sb = conn->lconn_sb;
|
||
|
+ sess = ldap_pvt_tls_sb_ctx( sb );
|
||
|
+ if ( sess != NULL )
|
||
|
+ return ldap_pvt_tls_get_peercert( sess, bv );
|
||
|
+ }
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
@@ -1020,6 +1037,13 @@ ldap_pvt_tls_get_unique( void *s, struct berval *buf, int is_server )
|
||
|
tls_session *session = s;
|
||
|
return tls_imp->ti_session_unique( session, buf, is_server );
|
||
|
}
|
||
|
+
|
||
|
+int
|
||
|
+ldap_pvt_tls_get_peercert( void *s, struct berval *der )
|
||
|
+{
|
||
|
+ tls_session *session = s;
|
||
|
+ return tls_imp->ti_session_peercert( session, der );
|
||
|
+}
|
||
|
#endif /* HAVE_TLS */
|
||
|
|
||
|
int
|
||
|
diff --git a/libraries/libldap/tls_g.c b/libraries/libldap/tls_g.c
|
||
|
index b78c12086..26d9f99ce 100644
|
||
|
--- a/libraries/libldap/tls_g.c
|
||
|
+++ b/libraries/libldap/tls_g.c
|
||
|
@@ -675,6 +675,24 @@ tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+tlsg_session_peercert( tls_session *sess, struct berval *der )
|
||
|
+{
|
||
|
+ tlsg_session *s = (tlsg_session *)sess;
|
||
|
+ const gnutls_datum_t *peer_cert_list;
|
||
|
+ unsigned int list_size;
|
||
|
+
|
||
|
+ peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size );
|
||
|
+ if (!peer_cert_list)
|
||
|
+ return -1;
|
||
|
+ der->bv_len = peer_cert_list[0].size;
|
||
|
+ der->bv_val = LDAP_MALLOC( der->bv_len );
|
||
|
+ if (!der->bv_val)
|
||
|
+ return -1;
|
||
|
+ memcpy(der->bv_val, peer_cert_list[0].data, der->bv_len);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
/* suites is a string of colon-separated cipher suite names. */
|
||
|
static int
|
||
|
tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites )
|
||
|
@@ -932,6 +950,7 @@ tls_impl ldap_int_tls_impl = {
|
||
|
tlsg_session_chkhost,
|
||
|
tlsg_session_strength,
|
||
|
tlsg_session_unique,
|
||
|
+ tlsg_session_peercert,
|
||
|
|
||
|
&tlsg_sbio,
|
||
|
|
||
|
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
|
||
|
index c64f4c176..d35a803de 100644
|
||
|
--- a/libraries/libldap/tls_m.c
|
||
|
+++ b/libraries/libldap/tls_m.c
|
||
|
@@ -2880,6 +2880,22 @@ tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+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
|
||
|
*/
|
||
|
@@ -3309,6 +3325,7 @@ tls_impl ldap_int_tls_impl = {
|
||
|
tlsm_session_chkhost,
|
||
|
tlsm_session_strength,
|
||
|
tlsm_session_unique,
|
||
|
+ tlsm_session_peercert,
|
||
|
|
||
|
&tlsm_sbio,
|
||
|
|
||
|
diff --git a/libraries/libldap/tls_o.c b/libraries/libldap/tls_o.c
|
||
|
index f741a461f..157923289 100644
|
||
|
--- a/libraries/libldap/tls_o.c
|
||
|
+++ b/libraries/libldap/tls_o.c
|
||
|
@@ -861,6 +861,21 @@ tlso_session_unique( tls_session *sess, struct berval *buf, int is_server)
|
||
|
return buf->bv_len;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+tlso_session_peercert( tls_session *sess, struct berval *der )
|
||
|
+{
|
||
|
+ tlso_session *s = (tlso_session *)sess;
|
||
|
+ unsigned char *ptr;
|
||
|
+ X509 *x = SSL_get_peer_certificate(s);
|
||
|
+ der->bv_len = i2d_X509(x, NULL);
|
||
|
+ der->bv_val = LDAP_MALLOC(der->bv_len);
|
||
|
+ if ( !der->bv_val )
|
||
|
+ return -1;
|
||
|
+ ptr = der->bv_val;
|
||
|
+ i2d_X509(x, &ptr);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* TLS support for LBER Sockbufs
|
||
|
*/
|
||
|
@@ -1379,6 +1394,7 @@ tls_impl ldap_int_tls_impl = {
|
||
|
tlso_session_chkhost,
|
||
|
tlso_session_strength,
|
||
|
tlso_session_unique,
|
||
|
+ tlso_session_peercert,
|
||
|
|
||
|
&tlso_sbio,
|
||
|
|
||
|
--
|
||
|
2.29.2
|
||
|
|