+ case LDAP_OPT_X_TLS_CACERT:
+ if ( lo->ldo_tls_cacert.bv_val )
+ LDAP_FREE( lo->ldo_tls_cacert.bv_val );
+ if ( arg ) {
+ lo->ldo_tls_cacert.bv_len = ((struct berval *)arg)->bv_len;
+ lo->ldo_tls_cacert.bv_val = LDAP_MALLOC( lo->ldo_tls_cacert.bv_len );
+ if ( !lo->ldo_tls_cacert.bv_val )
+ return -1;
+ AC_MEMCPY( lo->ldo_tls_cacert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cacert.bv_len );
+ } else {
+ BER_BVZERO( &lo->ldo_tls_cacert );
+ }
+ break;
+ case LDAP_OPT_X_TLS_CERT:
+ if ( lo->ldo_tls_cert.bv_val )
+ LDAP_FREE( lo->ldo_tls_cert.bv_val );
+ if ( arg ) {
+ lo->ldo_tls_cert.bv_len = ((struct berval *)arg)->bv_len;
+ lo->ldo_tls_cert.bv_val = LDAP_MALLOC( lo->ldo_tls_cert.bv_len );
+ if ( !lo->ldo_tls_cert.bv_val )
+ return -1;
+ AC_MEMCPY( lo->ldo_tls_cert.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_cert.bv_len );
+ } else {
+ BER_BVZERO( &lo->ldo_tls_cert );
+ }
+ break;
+ case LDAP_OPT_X_TLS_KEY:
+ if ( lo->ldo_tls_key.bv_val )
+ LDAP_FREE( lo->ldo_tls_key.bv_val );
+ if ( arg ) {
+ lo->ldo_tls_key.bv_len = ((struct berval *)arg)->bv_len;
+ lo->ldo_tls_key.bv_val = LDAP_MALLOC( lo->ldo_tls_key.bv_len );
+ if ( !lo->ldo_tls_key.bv_val )
+ return -1;
+ AC_MEMCPY( lo->ldo_tls_key.bv_val, ((struct berval *)arg)->bv_val, lo->ldo_tls_key.bv_len );
+ } else {
+ BER_BVZERO( &lo->ldo_tls_key );
+ }
+ break;
+ case LDAP_OPT_X_TLS_PEERKEY_HASH: {
+ /* arg = "[hashalg:]pubkey_hash" */
+ struct berval bv;
+ char *p, *pin = arg;
+ int rc = LDAP_SUCCESS;
+
+ if ( !tls_imp->ti_session_pinning ) return -1;
+
+ if ( !pin ) {
+ if ( lo->ldo_tls_pin_hashalg ) {
+ LDAP_FREE( lo->ldo_tls_pin_hashalg );
+ } else if ( lo->ldo_tls_pin.bv_val ) {
+ LDAP_FREE( lo->ldo_tls_pin.bv_val );
+ }
+ lo->ldo_tls_pin_hashalg = NULL;
+ BER_BVZERO( &lo->ldo_tls_pin );
+ return rc;
+ }
+
+ pin = LDAP_STRDUP( pin );
+ p = strchr( pin, ':' );
+
+ /* pubkey (its hash) goes in bv, alg in p */
+ if ( p ) {
+ *p = '\0';
+ bv.bv_val = p+1;
+ p = pin;
+ } else {
+ bv.bv_val = pin;
+ }
+
+ bv.bv_len = strlen(bv.bv_val);
+ if ( ldap_int_decode_b64_inplace( &bv ) ) {
+ LDAP_FREE( pin );
+ return -1;
+ }
+
+ if ( ld != NULL ) {
+ LDAPConn *conn = ld->ld_defconn;
+ if ( conn != NULL ) {
+ Sockbuf *sb = conn->lconn_sb;
+ void *sess = ldap_pvt_tls_sb_ctx( sb );
+ if ( sess != NULL ) {
+ rc = tls_imp->ti_session_pinning( ld, sess, p, &bv );
+ }
+ }
+ }
+
+ if ( rc == LDAP_SUCCESS ) {
+ if ( lo->ldo_tls_pin_hashalg ) {
+ LDAP_FREE( lo->ldo_tls_pin_hashalg );
+ } else if ( lo->ldo_tls_pin.bv_val ) {
+ LDAP_FREE( lo->ldo_tls_pin.bv_val );
+ }
+ lo->ldo_tls_pin_hashalg = p;
+ lo->ldo_tls_pin = bv;
+ } else {
+ LDAP_FREE( pin );
+ }
+
+ return rc;
+ }