]> git.sur5r.net Git - openldap/commitdiff
ITS#7398 add LDAP_OPT_X_TLS_PEERCERT
authorHoward Chu <hyc@openldap.org>
Tue, 10 Sep 2013 11:26:51 +0000 (04:26 -0700)
committerHoward Chu <hyc@openldap.org>
Tue, 10 Sep 2013 11:31:39 +0000 (04:31 -0700)
retrieve peer cert for an active TLS session

doc/man/man3/ldap_get_option.3
include/ldap.h
libraries/libldap/ldap-tls.h
libraries/libldap/tls2.c
libraries/libldap/tls_g.c
libraries/libldap/tls_m.c
libraries/libldap/tls_o.c

index e67de75e94b8673fb58444e8deac2c4b072678a9..1bb55d3576edce8438030296afc3f1d0a69d4181 100644 (file)
@@ -732,6 +732,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
index 4de3f7f322a3d1f02d538307e7180af6ba0d5524..97ca524d7509370761a71aca922321f0e8b66bec 100644 (file)
@@ -161,6 +161,7 @@ LDAP_BEGIN_DECL
 #define LDAP_OPT_X_TLS_ECNAME          0x6012
 #define LDAP_OPT_X_TLS_VERSION         0x6013  /* read-only */
 #define LDAP_OPT_X_TLS_CIPHER          0x6014  /* read-only */
+#define LDAP_OPT_X_TLS_PEERCERT                0x6015  /* read-only */
 
 #define LDAP_OPT_X_TLS_NEVER   0
 #define LDAP_OPT_X_TLS_HARD            1
index 548814d7fe1c671345d857e49f3f5f322917071c..890d20dc7ebfcfd59dc21b638df8d2a3e46bc0f1 100644 (file)
@@ -43,6 +43,7 @@ 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 const char *(TI_session_name)(tls_session *s);
+typedef int (TI_session_peercert)(tls_session *s, struct berval *der);
 
 typedef void (TI_thr_init)(void);
 
@@ -69,6 +70,7 @@ typedef struct tls_impl {
        TI_session_unique *ti_session_unique;
        TI_session_name *ti_session_version;
        TI_session_name *ti_session_cipher;
+       TI_session_peercert *ti_session_peercert;
 
        Sockbuf_IO *ti_sbio;
 
index 05fce3218b105271e89a4fbc3e47c9b1c86b7de5..cbf73bdd5a5e438d372e697b1c42dcbd45922969 100644 (file)
@@ -718,6 +718,22 @@ ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg )
                *(char **)arg = retval ? LDAP_STRDUP( retval ) : NULL;
                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;
@@ -1050,6 +1066,13 @@ ldap_pvt_tls_get_cipher( void *s )
        tls_session *session = s;
        return tls_imp->ti_session_cipher( session );
 }
+
+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
index ce422387c90a41796ef9ca6fa61b332008123ed9..7396804392fd0e1f3a2015dffd639655dd89ad44 100644 (file)
@@ -830,6 +830,24 @@ tlsg_session_cipher( tls_session *sess )
        return gnutls_cipher_get_name(gnutls_cipher_get( s->session ));
 }
 
+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 )
@@ -1166,6 +1184,7 @@ tls_impl ldap_int_tls_impl = {
        tlsg_session_unique,
        tlsg_session_version,
        tlsg_session_cipher,
+       tlsg_session_peercert,
 
        &tlsg_sbio,
 
index 4bd9e63cb5a8dea03e2464ecc89d5c107debe060..36dc989ef0c42fd84f226a6194e8ec2b10a5ccae 100644 (file)
@@ -2891,6 +2891,22 @@ tlsm_session_cipher( tls_session *sess )
        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
  */
@@ -3322,6 +3338,7 @@ tls_impl ldap_int_tls_impl = {
        tlsm_session_unique,
        tlsm_session_version,
        tlsm_session_cipher,
+       tlsm_session_peercert,
 
        &tlsm_sbio,
 
index 6288456d319d00ba6e5fb305bd0dd3e805c4827d..1fa50392f0e0a8490fbf63e208377a55c636634e 100644 (file)
@@ -721,6 +721,21 @@ tlso_session_cipher( tls_session *sess )
        return SSL_CIPHER_get_name(SSL_get_current_cipher(s));
 }
 
+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
  */
@@ -1229,6 +1244,7 @@ tls_impl ldap_int_tls_impl = {
        tlso_session_unique,
        tlso_session_version,
        tlso_session_cipher,
+       tlso_session_peercert,
 
        &tlso_sbio,