diff -uNr -x build openldap2-2.1.17.orig/configure.in openldap2-2.1.17/configure.in
--- openldap2-2.1.17.orig/configure.in	2003-03-05 17:48:30.000000000 -0600
+++ openldap2-2.1.17/configure.in	2003-06-27 10:08:47.000000000 -0500
@@ -158,7 +158,7 @@
 OL_ARG_WITH(threads,[  --with-threads	  with threads],
 	auto, [auto nt posix mach pth lwp yes no manual] )
 OL_ARG_WITH(tls,[  --with-tls		  with TLS/SSL support],
-	auto, [auto ssleay openssl yes no] )
+	auto, [auto ssleay openssl gnutls yes no] )
 OL_ARG_WITH(yielding_select,[  --with-yielding-select  with implicitly yielding select],
 	auto, [auto yes no manual] )
 
@@ -1226,9 +1226,18 @@
 dnl TLS/SSL
 ol_link_tls=no
 if test $ol_with_tls != no ; then
-	AC_CHECK_HEADERS(openssl/ssl.h ssl.h)
-	
-	if test $ac_cv_header_openssl_ssl_h = yes \
+	AC_CHECK_HEADERS(openssl/ssl.h ssl.h gnutls/gnutls.h)
+
+	if test $ac_cv_header_gnutls_gnutls_h = yes ; then
+		AC_CHECK_LIB(gnutls, gnutls_init,
+			[
+			ol_with_tls=found
+			ol_link_tls=yes
+			TLS_LIBS="-lgnutls -lgcrypt -ltasn1"
+			], [],
+			[-ltasn1 -lgcrypt])
+
+	elif test $ac_cv_header_openssl_ssl_h = yes \
 		-o $ac_cv_header_ssl_h = yes ; then
 		AC_CHECK_LIB(ssl, SSLeay_add_ssl_algorithms, 
 			[have_ssleay=yes
diff -uNr -x build openldap2-2.1.17.orig/include/ldap_pvt_gnutls.h openldap2-2.1.17/include/ldap_pvt_gnutls.h
--- openldap2-2.1.17.orig/include/ldap_pvt_gnutls.h	1969-12-31 18:00:00.000000000 -0600
+++ openldap2-2.1.17/include/ldap_pvt_gnutls.h	2003-06-28 23:29:23.000000000 -0500
@@ -0,0 +1,239 @@
+/* $OpenLDAP: Exp $ */
+/*
+ * Copyright 2003 Steve Langasek
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * ldap_pvt_gnutls.h - headers for the internal GNUTLS/OpenSSL wrapper
+ */
+
+#ifndef _LDAP_PVT_GNUTLS_H
+#define _LDAP_PVT_GNUTLS_H
+
+#ifdef HAVE_GNUTLS_GNUTLS_H
+#include <gnutls/gnutls.h>
+
+
+#define BIO_CTRL_FLUSH		11 /* Doesn't matter, we never use this. */
+
+#define BIO_FLAGS_READ		0x01
+#define BIO_FLAGS_WRITE		0x02
+#define BIO_FLAGS_IO_SPECIAL	0x04
+#define BIO_FLAGS_RWS		(BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL)
+#define BIO_FLAGS_SHOULD_RETRY	0x08
+
+#define BIO_set_flags(b,f) ((b)->flags|=(f))
+#define BIO_get_flags(b) ((b)->flags)
+#define BIO_set_retry_special(b) \
+		((b)->flags|=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_read(b) \
+		((b)->flags|=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_set_retry_write(b) \
+		((b)->flags|=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+
+/* These are normally used internally in BIOs */
+#define BIO_clear_flags(b,f) ((b)->flags&= ~(f))
+#define BIO_clear_retry_flags(b) \
+		((b)->flags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+#define BIO_get_retry_flags(b) \
+		((b)->flags&(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+
+#define SSL_VERIFY_NONE			0x00
+#define SSL_VERIFY_PEER			0x01
+#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT	0x02
+#define SSL_VERIFY_CLIENT_ONCE		0x04
+
+#define SSL_ERROR_NONE			0
+#define SSL_ERROR_WANT_READ		2
+#define SSL_ERROR_WANT_WRITE		3
+#define SSL_ERROR_WANT_CONNECT		7
+
+#define SSL3_AL_WARNING			GNUTLS_AL_WARNING
+#define SSL3_AD_BAD_CERTIFICATE		GNUTLS_A_BAD_CERTIFICATE
+
+#define ssl3_send_alert(ssl, level, type) gnutls_alert_send((ssl)->session, \
+								level, type);
+
+/* These are no-ops; just define them away. */
+#define SSL_load_error_strings() /* */
+#define X509V3_add_standard_extensions() /* */
+#define EVP_cleanup() /* */
+#define ERR_free_strings() /* */
+
+#define CRYPTO_free(x) free(x)
+
+
+typedef struct X509_STORE_CTX {
+    struct SSL *ssl;
+    int error;
+    const gnutls_datum *cert_list;
+} X509_STORE_CTX;
+
+/* Kludge: we don't really care about the semantics of OpenSSL stacks,
+   we just need to map STACK_OF(X509_NAME) to something unique so we can
+   typedef to the GNUTLS equivalent. */
+#define STACK_OF(x) x##_st
+
+typedef struct DSTRUCT X509_NAME_st;
+typedef gnutls_x509_dn X509_NAME;
+typedef gnutls_datum X509;
+
+typedef struct bio_decl BIO;
+
+typedef struct BIO_METHOD {
+	int type;
+	char *desc;
+	ssize_t (*write)(gnutls_transport_ptr, const void *, size_t);
+	ssize_t (*read)(gnutls_transport_ptr, void *, size_t);
+	int (*puts)(BIO *, const char *);
+	int (*gets)(BIO *, char *, int);
+	long (*ctrl)(BIO *, int, long, void *);
+	int (*create)(BIO *);
+	int (*destroy)(BIO *);
+} BIO_METHOD;
+
+struct bio_decl {
+    BIO_METHOD *method;
+    int init;
+    int num;
+    void *ptr;
+    int flags;
+};
+
+typedef struct
+{
+    int protocol_priority[GNUTLS_MAX_ALGORITHM_NUM];
+    int cipher_priority[GNUTLS_MAX_ALGORITHM_NUM];
+    int comp_priority[GNUTLS_MAX_ALGORITHM_NUM];
+    int kx_priority[GNUTLS_MAX_ALGORITHM_NUM];
+    int mac_priority[GNUTLS_MAX_ALGORITHM_NUM];
+    gnutls_connection_end connend;
+} SSL_METHOD;
+
+typedef struct SSL_CTX {
+	gnutls_certificate_credentials creds;
+	SSL_METHOD *method;
+	int verify_mode;
+	int (*verify_callback)(int, X509_STORE_CTX *);
+} SSL_CTX;
+
+/* This structure corresponds to the per-session state */
+typedef struct SSL {
+	gnutls_session session;
+	gnutls_cipher_algorithm cipher;
+	SSL_METHOD *method;
+	int verify_mode;
+	int (*verify_callback)(int, X509_STORE_CTX *);
+	int verify_result;
+	BIO *rbio;
+	BIO *wbio;
+	gnutls_certificate_credentials creds;
+} SSL;
+
+typedef gnutls_cipher_algorithm SSL_CIPHER;
+
+
+/* Mangle the function names, to prevent collisions with other functions
+   of the same name loaded by other libraries (i.e., OpenSSL) */
+#define ERR_get_error gnutls_ERR_get_error
+#define ERR_peek_error gnutls_ERR_peek_error
+#define ERR_error_string gnutls_ERR_error_string
+#define ERR_error_string_n gnutls_ERR_error_string_n
+#define ERR_get_error_line gnutls_ERR_get_error_line
+#define BIO_new gnutls_BIO_new
+#define X509_free gnutls_X509_free
+#define X509_get_subject_name gnutls_X509_get_subject_name
+#define X509_get_issuer_name gnutls_X509_get_issuer_name
+#define X509_NAME_oneline gnutls_X509_NAME_oneline
+#define X509_verify_cert_error_string gnutls_X509_verify_cert_error_string
+#define X509_STORE_CTX_get_current_cert gnutls_X509_STORE_CTX_get_current_cert 
+#define X509_STORE_CTX_get_error gnutls_X509_STORE_CTX_get_error
+#define X509_STORE_CTX_get_error_depth gnutls_X509_STORE_CTX_get_error_depth
+#define SSLeay_add_ssl_algorithms gnutls_SSLeay_add_ssl_algorithms
+#define SSLv23_method gnutls_SSLv23_method
+#define SSL_CIPHER_get_bits gnutls_SSL_CIPHER_get_bits
+#define SSL_CTX_free gnutls_SSL_CTX_free
+#define SSL_CTX_load_verify_locations gnutls_SSL_CTX_load_verify_locations
+#define SSL_CTX_new gnutls_SSL_CTX_new
+#define SSL_CTX_set_cipher_list gnutls_SSL_CTX_set_cipher_list
+#define SSL_CTX_set_client_CA_list gnutls_SSL_CTX_set_client_CA_list
+#define SSL_CTX_set_default_verify_paths gnutls_SSL_CTX_set_default_verify_paths
+#define SSL_CTX_set_session_id_context gnutls_SSL_CTX_set_session_id_context
+#define SSL_CTX_set_verify gnutls_SSL_CTX_set_verify
+#define SSL_accept gnutls_SSL_accept
+#define SSL_connect gnutls_SSL_connect
+#define SSL_free gnutls_SSL_free
+#define SSL_get_certificate gnutls_SSL_get_certificate
+#define SSL_get_current_cipher gnutls_SSL_get_current_cipher
+#define SSL_get_error gnutls_SSL_get_error
+#define SSL_get_peer_certificate gnutls_SSL_get_peer_certificate
+#define SSL_get_verify_result gnutls_SSL_get_verify_result
+#define SSL_new gnutls_SSL_new
+#define SSL_pending gnutls_SSL_pending
+#define SSL_read gnutls_SSL_read
+#define SSL_set_bio gnutls_SSL_set_bio
+#define SSL_shutdown gnutls_SSL_shutdown
+#define SSL_write gnutls_SSL_write
+
+int ERR_get_error(void);
+int ERR_peek_error(void);
+const char *ERR_error_string(int errnum, char *buf);
+const char *ERR_error_string_n(int errnum, char *buf, int buflen);
+unsigned long ERR_get_error_line(const char **file, int *line);
+
+BIO *BIO_new( BIO_METHOD *method );
+
+void X509_free(void *ptr);
+X509_NAME *X509_get_subject_name( const X509 *x );
+X509_NAME *X509_get_issuer_name( const X509 *x );
+char *X509_NAME_oneline( X509_NAME *dn, char *buf, int buflen );
+const char *X509_verify_cert_error_string( int errnum );
+const X509 *X509_STORE_CTX_get_current_cert( X509_STORE_CTX *ctx );
+int X509_STORE_CTX_get_error( X509_STORE_CTX *ctx );
+int X509_STORE_CTX_get_error_depth( X509_STORE_CTX *ctx );
+
+int SSLeay_add_ssl_algorithms(void);
+SSL_METHOD *SSLv23_method();
+void SSL_CTX_free( SSL_CTX *ctx );
+SSL_CTX *SSL_CTX_new( SSL_METHOD *method );
+int SSL_CTX_set_cipher_list( SSL_CTX *ctx, char *ciphersuite );
+int SSL_CTX_load_verify_locations( SSL_CTX *ctx, const char *CAfile,
+                                   const char *CApath );
+int SSL_CTX_set_default_verify_paths( SSL_CTX *ctx );
+int SSL_CTX_set_session_id_context( SSL_CTX *ctx, const unsigned char *sid_ctx,
+                                    unsigned int sid_ctx_len );
+void SSL_CTX_set_client_CA_list( SSL_CTX *ctx,
+                                 gnutls_certificate_credentials calist );
+void SSL_CTX_set_verify( SSL_CTX *ctx, int mode,
+                         int (*verify_callback)(int, X509_STORE_CTX *) );
+
+SSL *SSL_new( SSL_CTX * ctx );
+void SSL_free( SSL *ssl );
+int SSL_accept( SSL *ssl );
+int SSL_connect( SSL *ssl );
+int SSL_shutdown( SSL *ssl);
+int SSL_pending( SSL *ssl );
+int SSL_read( SSL *ssl, void *buf, int buflen );
+int SSL_write( SSL *ssl, const void *buf, int buflen );
+int SSL_get_error( SSL *ssl, int ret );
+SSL_CIPHER *SSL_get_current_cipher( SSL *ssl );
+int SSL_CIPHER_get_bits(SSL_CIPHER *cipher, int *alg_bits);
+X509 *SSL_get_certificate( SSL *ssl );
+X509 *SSL_get_peer_certificate( SSL *ssl );
+int SSL_get_verify_result( SSL *ssl );
+void SSL_set_bio( SSL *ssl, BIO *rbio, BIO *wbio );
+
+#endif
+#endif
diff -uNr -x build openldap2-2.1.17.orig/libraries/libldap/Makefile.in openldap2-2.1.17/libraries/libldap/Makefile.in
--- openldap2-2.1.17.orig/libraries/libldap/Makefile.in	2003-03-30 08:47:09.000000000 -0600
+++ openldap2-2.1.17/libraries/libldap/Makefile.in	2003-06-28 21:28:25.000000000 -0500
@@ -16,7 +16,8 @@
 	getdn.c getentry.c getattr.c getvalues.c addentry.c \
 	request.c os-ip.c url.c sortctrl.c vlvctrl.c \
 	init.c options.c print.c string.c util-int.c schema.c \
-	charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c
+	charray.c tls.c gnutls.c os-local.c dnssrv.c utf-8.c \
+	utf-8-conv.c
 OBJS	= bind.lo open.lo result.lo error.lo compare.lo search.lo \
 	controls.lo messages.lo references.lo extended.lo cyrus.lo \
 	modify.lo add.lo modrdn.lo delete.lo abandon.lo \
@@ -25,7 +26,8 @@
 	getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
 	request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
 	init.lo options.lo print.lo string.lo util-int.lo schema.lo \
-	charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo
+	charray.lo tls.lo gnutls.lo os-local.lo dnssrv.lo utf-8.lo \
+	utf-8-conv.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
diff -uNr -x build openldap2-2.1.17.orig/libraries/libldap/getdn.c openldap2-2.1.17/libraries/libldap/getdn.c
--- openldap2-2.1.17.orig/libraries/libldap/getdn.c	2003-03-03 11:10:04.000000000 -0600
+++ openldap2-2.1.17/libraries/libldap/getdn.c	2003-06-25 23:27:37.000000000 -0500
@@ -3341,6 +3341,23 @@
 }
 
 #ifdef HAVE_TLS
+#ifdef HAVE_GNUTLS_GNUTLS_H
+
+/* Stub function: disable this for now, there's a lot of conversion
+ * code that needs to be written to make this work with GNUTLS (OIDs, etc).
+ */
+int
+ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
+	unsigned flags )
+{
+	assert( bv );
+	bv->bv_len = 0;
+	bv->bv_val = NULL;
+
+	return LDAP_SUCCESS;
+}
+
+#else
 #include <openssl/x509.h>
 #include <openssl/err.h>
 
@@ -3537,5 +3554,7 @@
 		LDAP_FREE( newDN );
 	return rc;
 }
+#endif /* HAVE_GNUTLS_GNUTLS_H */
+
 #endif /* HAVE_TLS */
 
diff -uNr -x build openldap2-2.1.17.orig/libraries/libldap/gnutls.c openldap2-2.1.17/libraries/libldap/gnutls.c
--- openldap2-2.1.17.orig/libraries/libldap/gnutls.c	1969-12-31 18:00:00.000000000 -0600
+++ openldap2-2.1.17/libraries/libldap/gnutls.c	2003-06-28 21:42:26.000000000 -0500
@@ -0,0 +1,635 @@
+/* $OpenLDAP: Exp $ */
+/*
+ * Copyright 2003 Steve Langasek
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * gnutls.c - Compatibility wrapper for calling GNU TLS with the OpenSSL API
+ */
+
+#include "portable.h"
+#include "ldap_config.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/ctype.h>
+#include <ac/unistd.h>
+
+#include "ldap-int.h"
+
+#ifdef HAVE_GNUTLS_GNUTLS_H
+
+#include <gnutls/gnutls.h>
+#include "ldap_pvt_gnutls.h"
+
+/* XXX: who designed this lousy API? */
+static int gnutls_error = 0;
+
+int
+ERR_get_error(void)
+{
+	int ret = (gnutls_error * -1);
+	gnutls_error = 0;
+	return ret;
+}
+
+int
+ERR_peek_error(void)
+{
+	return (gnutls_error * -1);
+}
+
+const char *
+ERR_error_string(int errnum, char *buf)
+{
+	return gnutls_strerror(errnum * -1);
+}
+
+const char *
+ERR_error_string_n(int errnum, char *buf, int buflen)
+{
+	const char *tmpbuf = gnutls_strerror(errnum);
+	if (buf && tmpbuf) {
+		strncpy(buf,tmpbuf,buflen-1);
+		buf[buflen-1] = '\0';
+	}
+	return tmpbuf;
+}
+
+unsigned long
+ERR_get_error_line(const char **file, int *line)
+{
+	int ret;
+
+	*file = NULL;
+	*line = 0;
+	ret = gnutls_error;
+	gnutls_error = 0;
+	return ret;
+}
+
+BIO *
+BIO_new( BIO_METHOD *method )
+{
+	BIO *bio = malloc(sizeof(*bio));
+
+	if (!bio)
+		return NULL;
+
+	if (method->create) {
+		if (!method->create(bio) || !bio->init) {
+			free(bio);
+			return NULL;
+		}
+	}
+	bio->init = 1;
+	bio->method = method;
+	return bio;
+}
+
+/* These are handled by the gnutls_deinit() function; trying to free
+   them directly yields a segfault. */
+void X509_free(void *ptr) {
+	return;
+}
+
+X509_NAME *
+X509_get_subject_name( const X509 *x )
+{
+	X509_NAME *dn = NULL;
+
+	if (!x)
+		return NULL;
+
+	if (!(dn = malloc(sizeof(*dn))))
+		return NULL;
+
+	if (gnutls_x509_extract_certificate_dn( x, dn )) {
+		free(dn);
+		return NULL;
+	}
+
+	return dn;
+}
+
+X509_NAME *
+X509_get_issuer_name( const X509 *x )
+{
+	X509_NAME *dn = NULL;
+
+	if (!x)
+		return NULL;
+
+	if (!(dn = malloc(sizeof(*dn))))
+		return NULL;
+
+	if (gnutls_x509_extract_certificate_issuer_dn( x, dn )) {
+		free(dn);
+		return NULL;
+	}
+
+	return dn;
+}
+
+char *
+X509_NAME_oneline( X509_NAME *dn, char *buf, int buflen )
+{
+	if (!dn)
+		return NULL;
+
+	if (!buf) {
+		buflen = strlen(dn->country)
+		         + strlen(dn->state_or_province_name)
+		         + strlen(dn->locality_name)
+		         + strlen(dn->organization)
+		         + strlen(dn->organizational_unit_name)
+		         + strlen(dn->common_name) + strlen(dn->email)
+		         + 33;
+		buf = (char *)malloc(buflen);
+	}
+	if (!buf)
+		return NULL;
+
+	snprintf(buf, buflen, "C=%s, ST=%s, L=%s, O=%s, OU=%s, CN=%s/Email=%s",
+	         dn->country, dn->state_or_province_name, dn->locality_name,
+	         dn->organization, dn->organizational_unit_name,
+	         dn->common_name, dn->email);
+	buf[buflen-1] = '\0';
+	return buf;
+}
+
+const char *
+X509_verify_cert_error_string( int errnum )
+{
+	switch (errnum) {
+	case GNUTLS_CERT_NOT_TRUSTED:
+		return "No trusted path to certificate";
+	case GNUTLS_CERT_INVALID:
+		return "Certificate is invalid";
+	case GNUTLS_CERT_CORRUPTED:
+		return "Certificate is corrupted";
+	case GNUTLS_CERT_REVOKED:
+		return "Certificate has been revoked";
+	case 0:
+		return "No error";
+	default:
+		return "Unknown error";
+	}
+}
+
+const X509 *
+X509_STORE_CTX_get_current_cert( X509_STORE_CTX *ctx )
+{
+	if (!ctx)
+		return NULL;
+	return ctx->cert_list;
+}
+
+int
+X509_STORE_CTX_get_error( X509_STORE_CTX *ctx )
+{
+	if (!ctx)
+		return -1;
+	return ctx->error;
+}
+
+int
+X509_STORE_CTX_get_error_depth( X509_STORE_CTX *ctx )
+{
+	/* XXX: gnutls doesn't seem to track CA chain depth. */
+	return 0;
+}
+
+int
+SSLeay_add_ssl_algorithms(void)
+{
+	if ((gnutls_error = gnutls_global_init()) < 0) {
+		return 0;
+	}
+	return 1;
+}
+
+SSL_METHOD *
+SSLv23_method() {
+	SSL_METHOD *method;
+
+	method = calloc(1, sizeof(*method));
+	if (!method)
+		return NULL;
+
+	method->protocol_priority[0] = GNUTLS_TLS1;
+	method->protocol_priority[1] = GNUTLS_SSL3;
+	method->protocol_priority[2] = 0;
+
+	method->cipher_priority[0] = GNUTLS_CIPHER_RIJNDAEL_128_CBC;
+	method->cipher_priority[1] = GNUTLS_CIPHER_3DES_CBC;
+	method->cipher_priority[2] = GNUTLS_CIPHER_RIJNDAEL_256_CBC;
+	method->cipher_priority[3] = GNUTLS_CIPHER_ARCFOUR_128;
+	method->cipher_priority[4] = 0;
+
+	method->comp_priority[0] = GNUTLS_COMP_ZLIB;
+	method->comp_priority[1] = GNUTLS_COMP_NULL;
+	method->comp_priority[2] = 0;
+
+	method->kx_priority[0] = GNUTLS_KX_DHE_RSA;
+	method->kx_priority[1] = GNUTLS_KX_RSA;
+	method->kx_priority[2] = GNUTLS_KX_DHE_DSS;
+	method->kx_priority[3] = 0;
+
+	method->mac_priority[0] = GNUTLS_MAC_SHA;
+	method->mac_priority[1] = GNUTLS_MAC_MD5;
+	method->mac_priority[2] = 0;
+
+	return method;
+}
+
+void
+SSL_CTX_free( SSL_CTX *ctx )
+{
+	if (!ctx)
+		return;
+
+	if (ctx->creds)
+		gnutls_certificate_free_credentials(ctx->creds);
+	if (ctx->method)
+		free(ctx->method);
+	free(ctx);
+
+	/* XXX: this *really* doesn't belong here, but in practice,
+	   we're using a global context anyway. */
+	gnutls_global_deinit();
+}
+
+SSL_CTX *
+SSL_CTX_new( SSL_METHOD *method )
+{
+	SSL_CTX *ctx = NULL;
+
+	ctx = calloc(1,sizeof(*ctx));
+	if (ctx)
+		ctx->method = method;
+
+	return ctx;
+}
+
+int
+SSL_CTX_set_cipher_list( SSL_CTX *ctx, char *ciphersuite )
+{
+	/* XXX: GNUTLS seems to ignore this; we will, too; but
+	   it should be handled by converting the string to a
+	   prioritized cipher list. */
+	return 1;
+}
+
+/* These we ignore because I don't see that they do anything useful. */
+int
+SSL_CTX_load_verify_locations( SSL_CTX *ctx, const char *CAfile,
+                               const char *CApath )
+{
+	return 1;
+}
+
+int
+SSL_CTX_set_default_verify_paths( SSL_CTX *ctx )
+{
+	return 1;
+}
+
+int
+SSL_CTX_set_session_id_context( SSL_CTX *ctx, const unsigned char *sid_ctx,
+                                unsigned int sid_ctx_len )
+{
+	return 1;
+}
+
+void
+SSL_CTX_set_client_CA_list( SSL_CTX *ctx,
+                            gnutls_certificate_credentials calist )
+{
+	if (!ctx)
+		return;
+
+	if (ctx->creds) {
+		gnutls_certificate_free_credentials(ctx->creds);
+	}
+	ctx->creds = calist;
+}
+
+
+void
+SSL_CTX_set_verify( SSL_CTX *ctx, int mode,
+                    int (*verify_callback)(int, X509_STORE_CTX *) )
+{
+	if (!ctx)
+		return;
+
+	ctx->verify_mode = mode;
+	ctx->verify_callback = verify_callback;
+}
+
+SSL *
+SSL_new( SSL_CTX * ctx )
+{
+	SSL *ssl = calloc(1,sizeof(*ssl));
+
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_MEMORY_ERROR;
+		return NULL;
+	}
+
+	ssl->session = NULL;
+
+	if (ctx) {
+		ssl->verify_mode = ctx->verify_mode;
+		ssl->verify_callback = ctx->verify_callback;
+		ssl->creds = ctx->creds;
+		ssl->method = ctx->method;
+	}
+	return ssl;
+}
+
+void
+SSL_free( SSL *ssl )
+{
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return;
+	}
+
+	if (ssl->session)
+		gnutls_deinit(ssl->session);
+
+	free(ssl);
+}
+
+static int
+SSL_do_handshake( SSL *ssl, gnutls_connection_end end )
+{
+	int cert_list_length;
+	int ret;
+	const gnutls_datum *cert_list;
+	X509_STORE_CTX *x509_store;
+
+	/* Initialize the session here, not in SSL_new(), because this
+	   is the first place we know which side of the connection we're
+	   on. */
+	if (!ssl->session) {
+		if ((gnutls_error = gnutls_init(&ssl->session, end)) < 0)
+		{
+			return 0;
+		}
+
+		gnutls_protocol_set_priority(ssl->session,
+		                             ssl->method->protocol_priority);
+		gnutls_cipher_set_priority(ssl->session,
+		                           ssl->method->cipher_priority);
+		gnutls_compression_set_priority(ssl->session,
+		                                ssl->method->comp_priority);
+		gnutls_kx_set_priority(ssl->session, ssl->method->kx_priority);
+		gnutls_mac_set_priority(ssl->session,
+		                        ssl->method->mac_priority);
+
+		gnutls_transport_set_ptr2(ssl->session,
+		                          (gnutls_transport_ptr)ssl->rbio,
+		                          (gnutls_transport_ptr)ssl->wbio);
+
+		if (ssl->rbio && ssl->rbio->init) {
+			gnutls_transport_set_pull_function(ssl->session,
+			                                   ssl->rbio->method->read);
+		}
+
+		if (ssl->wbio && ssl->wbio->init) {
+			gnutls_transport_set_push_function(ssl->session,
+			                                   ssl->wbio->method->write);
+		}
+
+		/* TODO: parse the cipher list OpenSSL uses, and import it
+		   to a cipher_priority list. */
+
+		/* Ignore any failures here; maybe we can get by without
+		   any credentials at all? Or should we only ignore errors
+		   if we don't require ca verification? */
+		gnutls_credentials_set(ssl->session, GNUTLS_CRD_CERTIFICATE, 
+		                       ssl->creds);
+
+	}
+
+	gnutls_error = gnutls_handshake(ssl->session);
+	if (gnutls_error < 0)
+		return gnutls_error;
+
+	cert_list = gnutls_certificate_get_peers(ssl->session,
+	                                         &cert_list_length);
+
+	ret = gnutls_certificate_verify_peers(ssl->session);
+
+	x509_store = malloc(sizeof(*x509_store));
+	if (x509_store) {
+		x509_store->ssl = ssl;
+		x509_store->cert_list = cert_list;
+		x509_store->error = ret;
+	}
+
+	/* The callback wants a boolean, not an error code. */
+	ssl->verify_result = !ret;
+
+	if (ssl->verify_callback)
+		ssl->verify_result = ssl->verify_callback(ssl->verify_result,
+							  x509_store);
+
+	free(x509_store);
+
+	if (!ssl->verify_result && ssl->verify_mode != SSL_VERIFY_NONE)
+	{
+		if (ret == GNUTLS_CERT_CORRUPTED)
+			gnutls_error = GNUTLS_E_NO_CERTIFICATE_FOUND;
+		else
+			gnutls_error = GNUTLS_E_CERTIFICATE_ERROR;
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+SSL_accept( SSL *ssl )
+{
+	return SSL_do_handshake(ssl, GNUTLS_SERVER);
+}
+
+int
+SSL_connect( SSL *ssl )
+{
+	return SSL_do_handshake(ssl, GNUTLS_CLIENT);
+}
+
+int
+SSL_shutdown( SSL *ssl)
+{
+	if (!ssl || !ssl->session) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return 0;
+	}
+	gnutls_error = gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
+	return (!gnutls_error);
+}
+
+int
+SSL_pending( SSL *ssl )
+{
+	if (!ssl)
+		return 0;
+	return gnutls_record_check_pending(ssl->session);
+}
+
+int
+SSL_read( SSL *ssl, void *buf, int buflen )
+{
+	int ret;
+
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return 0;
+	}
+	ret = gnutls_read(ssl->session, buf, buflen);
+	if (ret < 0)
+		gnutls_error = ret;
+
+	return ret;
+}
+
+
+int
+SSL_write( SSL *ssl, const void *buf, int buflen )
+{
+	int ret;
+
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return 0;
+	}
+	ret = gnutls_write(ssl->session, buf, buflen);
+	if (ret < 0)
+		gnutls_error = ret;
+
+	return ret;
+}
+
+int
+SSL_get_error( SSL *ssl, int ret )
+{
+	/* XXX: aren't these the same errors returned by read? */
+	if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
+		return SSL_ERROR_WANT_WRITE;
+	/* This should only happen on read; we ignore it, because we
+	   have no sane way to react to it. */
+	if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
+		return SSL_ERROR_WANT_READ;
+
+	return SSL_ERROR_NONE;
+}
+
+SSL_CIPHER *
+SSL_get_current_cipher( SSL *ssl )
+{
+	ssl->cipher = gnutls_cipher_get(ssl->session);
+	return &ssl->cipher;
+}
+
+int
+SSL_CIPHER_get_bits(SSL_CIPHER *cipher, int *alg_bits)
+{
+	int bits;
+
+	if (!cipher)
+		return 0;
+
+	bits = gnutls_cipher_get_key_size(*cipher) * 8;
+
+	if (alg_bits)
+		*alg_bits = bits;
+
+	return bits;
+}
+
+X509 *
+SSL_get_certificate( SSL *ssl )
+{
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return NULL;
+	}
+	return (X509 *)gnutls_certificate_get_ours(ssl->session);
+}
+
+X509 *
+SSL_get_peer_certificate( SSL *ssl )
+{
+	int list_size = 0;
+
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return NULL;
+	}
+	return (X509 *)gnutls_certificate_get_peers(ssl->session, &list_size);
+}
+
+int 
+SSL_get_verify_result( SSL *ssl )
+{
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return 1;
+	}
+	/* XXX: why does the meaning of this keep switching? :P */
+	return !ssl->verify_result;
+}
+
+void
+SSL_set_bio( SSL *ssl, BIO *rbio, BIO *wbio )
+{
+	gnutls_error = GNUTLS_E_SUCCESS;
+
+	if (!ssl) {
+		gnutls_error = GNUTLS_E_INVALID_SESSION;
+		return;
+	}
+
+	/* This may be called before we have all the pieces to set up
+	   the session. */
+	ssl->rbio = rbio;
+	ssl->wbio = wbio;
+
+	if (ssl->session) {
+		gnutls_transport_set_ptr2(ssl->session,
+		                          (gnutls_transport_ptr)rbio,
+		                          (gnutls_transport_ptr)wbio);
+
+		if (rbio && rbio->init) {
+			gnutls_transport_set_pull_function(ssl->session,
+			                                   rbio->method->read);
+		}
+
+		if (wbio && wbio->init) {
+			gnutls_transport_set_push_function(ssl->session,
+			                                   wbio->method->write);
+		}
+	}
+}
+
+#endif
+
diff -uNr -x build openldap2-2.1.17.orig/libraries/libldap/tls.c openldap2-2.1.17/libraries/libldap/tls.c
--- openldap2-2.1.17.orig/libraries/libldap/tls.c	2003-02-08 17:28:51.000000000 -0600
+++ openldap2-2.1.17/libraries/libldap/tls.c	2003-06-28 23:46:57.000000000 -0500
@@ -29,7 +29,10 @@
 #include <ldap_pvt_thread.h>
 #endif
 
-#ifdef HAVE_OPENSSL_SSL_H
+#ifdef HAVE_GNUTLS_GNUTLS_H
+#include <gnutls/gnutls.h>
+#include "ldap_pvt_gnutls.h"
+#elif defined(HAVE_OPENSSL_SSL_H)
 #include <openssl/ssl.h>
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
@@ -53,10 +56,13 @@
 
 static void tls_report_error( void );
 
+#ifndef HAVE_GNUTLS_GNUTLS_H
 static void tls_info_cb( const SSL *ssl, int where, int ret );
+static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
+#endif
+
 static int tls_verify_cb( int ok, X509_STORE_CTX *ctx );
 static int tls_verify_ok( int ok, X509_STORE_CTX *ctx );
-static RSA * tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length );
 static STACK_OF(X509_NAME) * get_ca_list( char * bundle, char * dir );
 
 #if 0	/* Currently this is not used by anyone */
@@ -68,6 +74,8 @@
 static int tls_seed_PRNG( const char *randfile );
 
 #ifdef LDAP_R_COMPILE
+
+#ifndef HAVE_GNUTLS_GNUTLS_H
 /*
  * provide mutexes for the SSLeay library.
  */
@@ -81,6 +89,7 @@
 		ldap_pvt_thread_mutex_unlock( &tls_mutexes[type] );
 	}
 }
+#endif
 
 /*
  * an extra mutex for the default ctx.
@@ -92,10 +101,12 @@
 {
 	int i;
 
+#ifndef HAVE_GNUTLS_GNUTLS_H
 	for( i=0; i< CRYPTO_NUM_LOCKS ; i++ ) {
 		ldap_pvt_thread_mutex_init( &tls_mutexes[i] );
 	}
 	CRYPTO_set_locking_callback( tls_locking_cb );
+#endif
 	/* FIXME: the thread id should be added somehow... */
 
 	ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex );
@@ -298,6 +309,49 @@
 			SSL_CTX_set_client_CA_list( tls_def_ctx, calist );
 		}
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+
+		/* This is already initialized if we have a CA list above */
+		if (!tls_def_ctx->creds)
+			gnutls_certificate_allocate_credentials( &tls_def_ctx->creds );
+
+		if (gnutls_certificate_set_x509_key_file( tls_def_ctx->creds,
+				certfile, keyfile, GNUTLS_X509_FMT_PEM ) )
+		{
+			if (tls_opt_keyfile)
+			{
+#ifdef NEW_LOGGING
+				LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_init_def_ctx: "
+					"TLS could not use key file `%s'.\n", tls_opt_keyfile, 0, 0 );
+#else
+				Debug( LDAP_DEBUG_ANY,
+					"TLS: could not use key file `%s'.\n",
+					tls_opt_keyfile,0,0);
+#endif
+				tls_report_error();
+				rc = -1;
+				goto error_exit;
+
+			}
+			if (tls_opt_certfile)
+			{
+#ifdef NEW_LOGGING
+				LDAP_LOG ( TRANSPORT, ERR,
+					"ldap_pvt_tls_init_def_ctx: "
+					"TLS could not use certificate `%s'.\n", 
+					tls_opt_certfile, 0, 0 );
+#else
+				Debug( LDAP_DEBUG_ANY,
+					"TLS: could not use certificate `%s'.\n",
+					tls_opt_certfile,0,0);
+#endif
+				tls_report_error();
+				rc = -1;
+				goto error_exit;
+
+			}
+		}
+#else
 		if ( tls_opt_keyfile &&
 			!SSL_CTX_use_PrivateKey_file( tls_def_ctx,
 				keyfile, SSL_FILETYPE_PEM ) )
@@ -350,9 +404,11 @@
 			goto error_exit;
 		}
 
+		/* No trace option supported with GNUTLS. */
 		if ( tls_opt_trace ) {
 			SSL_CTX_set_info_callback( tls_def_ctx, tls_info_cb );
 		}
+#endif	/* HAVE_GNUTLS_GNUTLS_H */
 
 		i = SSL_VERIFY_NONE;
 		if ( tls_opt_require_cert ) {
@@ -366,7 +422,10 @@
 		SSL_CTX_set_verify( tls_def_ctx, i,
 			tls_opt_require_cert == LDAP_OPT_X_TLS_ALLOW ?
 			tls_verify_ok : tls_verify_cb );
+/* XXX: what's this good for? */
+#ifndef HAVE_GNUTLS_GNUTLS_H
 		SSL_CTX_set_tmp_rsa_callback( tls_def_ctx, tls_tmp_rsa_cb );
+#endif
 		/* SSL_CTX_set_tmp_dh_callback( tls_def_ctx, tls_tmp_dh_cb ); */
 	}
 error_exit:
@@ -393,9 +452,15 @@
 	STACK_OF(X509_NAME) *ca_list = NULL;
 
 	if ( bundle ) {
+#ifdef HAVE_GNUTLS_GNUTLS_H
+		gnutls_certificate_allocate_credentials( &ca_list );
+		gnutls_certificate_set_x509_trust_file( ca_list,
+			bundle, GNUTLS_X509_FMT_PEM );
+#else
 		ca_list = SSL_load_client_CA_file( bundle );
+#endif
 	}
-#if defined(HAVE_DIRENT_H) || defined(dirent)
+#if !defined(HAVE_GNUTLS_GNUTLS_H) && (defined(HAVE_DIRENT_H) || defined(dirent))
 	if ( dir ) {
 		int freeit = 0;
 
@@ -628,15 +693,20 @@
 	return 1;
 }
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+static ssize_t
+sb_tls_bio_read( gnutls_transport_ptr b, void *buf, size_t len )
+#else
 static int
 sb_tls_bio_read( BIO *b, char *buf, int len )
+#endif
 {
 	struct tls_data		*p;
 	int			ret;
 		
 	if ( buf == NULL || len <= 0 ) return 0;
 
-	p = (struct tls_data *)b->ptr;
+	p = (struct tls_data *)((BIO *)b)->ptr;
 
 	if ( p == NULL || p->sbiod == NULL ) {
 		return 0;
@@ -644,26 +714,31 @@
 
 	ret = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
 
-	BIO_clear_retry_flags( b );
+	BIO_clear_retry_flags( ((BIO *)b) );
 	if ( ret < 0 ) {
 		int err = errno;
 		if ( err == EAGAIN || err == EWOULDBLOCK ) {
-			BIO_set_retry_read( b );
+			BIO_set_retry_read( ((BIO *)b) );
 		}
 	}
 
 	return ret;
 }
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+static ssize_t
+sb_tls_bio_write( gnutls_transport_ptr b, const void *buf, size_t len )
+#else
 static int
 sb_tls_bio_write( BIO *b, const char *buf, int len )
+#endif
 {
 	struct tls_data		*p;
 	int			ret;
 	
 	if ( buf == NULL || len <= 0 ) return 0;
 	
-	p = (struct tls_data *)b->ptr;
+	p = (struct tls_data *)((BIO *)b)->ptr;
 
 	if ( p == NULL || p->sbiod == NULL ) {
 		return 0;
@@ -671,11 +746,11 @@
 
 	ret = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
 
-	BIO_clear_retry_flags( b );
+	BIO_clear_retry_flags( ((BIO *)b) );
 	if ( ret < 0 ) {
 		int err = errno;
 		if ( err == EAGAIN || err == EWOULDBLOCK ) {
-			BIO_set_retry_write( b );
+			BIO_set_retry_write( ((BIO *)b) );
 		}
 	}
 
@@ -893,6 +968,8 @@
 	
 	xn = X509_get_subject_name(x);
 	rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags );
+	free(xn);
+	X509_free(x);
 	return rc;
 }
 
@@ -902,7 +979,12 @@
 	/* If peer cert was bad, treat as if no cert was given */
 	if (SSL_get_verify_result(s)) {
 		/* If we can send an alert, do so */
+#ifndef HAVE_GNUTLS_GNUTLS_H
 		if (SSL_version(s) != SSL2_VERSION) {
+#else
+		/* GNUTLS doesn't support version 2. */
+		{
+#endif
 			ssl3_send_alert(s,SSL3_AL_WARNING,SSL3_AD_BAD_CERTIFICATE);
 		}
 		return NULL;
@@ -923,6 +1005,7 @@
 	
 	xn = X509_get_subject_name(x);
 	rc = ldap_X509dn2bv(xn, dn, (LDAPDN_rewrite_func *)func, flags);
+	free(xn);
 	X509_free(x);
 	return rc;
 }
@@ -931,13 +1014,26 @@
 ldap_pvt_tls_get_peer_hostname( void *s )
 {
 	X509 *x;
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	X509_NAME xn;
+#else
 	X509_NAME *xn;
+#endif
 	char buf[2048], *p;
 	int ret;
 
 	x = tls_get_cert((SSL *)s);
 	if (!x) return NULL;
 	
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	if (gnutls_x509_extract_certificate_dn( x, &xn ))
+	{
+		X509_free(x);
+		return NULL;
+	}
+
+	p = LDAP_STRDUP(xn.common_name);
+#else
 	xn = X509_get_subject_name(x);
 
 	ret = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf));
@@ -947,6 +1043,7 @@
 	}
 
 	p = LDAP_STRDUP(buf);
+#endif
 	X509_free(x);
 	return p;
 }
@@ -964,6 +1061,9 @@
 	const char *name;
 	char *ptr;
 	int ntype = IS_DNS;
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	int tlsret, alttype;
+#endif
 #ifdef LDAP_PF_INET6
 	struct in6_addr addr;
 #else
@@ -1008,7 +1108,68 @@
 		if (inet_aton(name, (struct in_addr *)&addr))
 			ntype = IS_IP4;
 	}
-	
+
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	/* XXX: we /could/ use gnutls_x509_check_certificates_hostname()
+	   here, but it only checks hostnames -- not IPs. */
+	if (ntype == IS_DNS)
+		alttype = GNUTLS_SAN_DNSNAME;
+	else
+		alttype = GNUTLS_SAN_IPADDRESS;
+
+	/* FIXME: do we care about GNUTLS_E_SHORT_MEMORY_BUFFER errors? */
+	do {
+		char buffer[512];
+		int sl;
+		int len1 = 0, len2 = 0;
+		char *domain = NULL;
+
+		sl = sizeof(buffer);
+		tlsret = gnutls_x509_extract_certificate_subject_alt_name(
+					x, i++, buffer, &sl
+		         );
+
+		if (tlsret != alttype || sl <= 0)
+			continue;
+
+		/* Is this an exact match? */
+		if ((len1 == sl)
+		    && !strncasecmp(name, buffer, len1))
+		{
+			ret = LDAP_SUCCESS;
+			break;
+		}
+
+		if (ntype == IS_DNS) {
+			/* XXX: doesn't belong inside the loop. */
+			len1 = strlen(name);
+			domain = strchr(name, '.');
+			if (domain) {
+				len2 = len1 - (domain-name);
+			}
+			/* XXX: doesn't belong inside the loop. */
+
+			/* Is this a wildcard match? */
+			if ((*buffer == '*') && domain && (len2 == sl-1) &&
+				!strncasecmp(domain, buffer+1, len2))
+			{
+				ret = LDAP_SUCCESS;
+				break;
+			}
+
+#if 0
+			/* Is this a RFC 2459 style wildcard match? */
+			if ((*sn == '.') && domain && (len2 == sl) &&
+				!strncasecmp(domain, buffer, len2))
+			{
+				ret = LDAP_SUCCESS;
+				break;
+			}
+#endif
+		}
+	} while (tlsret >= 0);
+
+#else
 	i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
 	if (i >= 0) {
 		X509_EXTENSION *ex;
@@ -1083,15 +1244,20 @@
 			}
 		}
 	}
+#endif /* HAVE_GNUTLS_GNUTLS_H */
 
 	if (ret != LDAP_SUCCESS) {
 		X509_NAME *xn;
 		char buf[2048];
 
 		xn = X509_get_subject_name(x);
-
+#ifdef HAVE_GNUTLS_GNUTLS_H
+		buf[sizeof(buf)-1] = '\0';
+		if (!xn || !strncpy(buf, xn->common_name, sizeof(buf)-1))
+#else
 		if( X509_NAME_get_text_by_NID( xn, NID_commonName,
 			buf, sizeof(buf)) == -1)
+#endif
 		{
 #ifdef NEW_LOGGING
 			LDAP_LOG ( TRANSPORT, ERR, "ldap_pvt_tls_check_hostname: "
@@ -1419,6 +1585,9 @@
 	return LDAP_SUCCESS;
 }
 
+/* XXX: These callbacks aren't used in the gnutls API. Why? */
+
+#ifndef HAVE_GNUTLS_GNUTLS_H
 /* Derived from openssl/apps/s_cb.c */
 static void
 tls_info_cb( const SSL *ssl, int where, int ret )
@@ -1506,11 +1675,12 @@
 	if ( state ) LDAP_FREE( state );
 #endif
 }
+#endif
 
 static int
 tls_verify_cb( int ok, X509_STORE_CTX *ctx )
 {
-	X509 *cert;
+	const X509 *cert;
 	int errnum;
 	int errdepth;
 	X509_NAME *subject;
@@ -1532,6 +1702,11 @@
 	/* X509_NAME_oneline, if passed a NULL buf, allocate memomry */
 	sname = X509_NAME_oneline( subject, NULL, 0 );
 	iname = X509_NAME_oneline( issuer, NULL, 0 );
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	free(issuer);
+	free(subject);
+#endif
+
 	if ( !ok ) certerr = (char *)X509_verify_cert_error_string( errnum );
 #ifdef HAVE_EBCDIC
 	if ( sname ) __etoa( sname );
@@ -1613,6 +1788,8 @@
 	}
 }
 
+/* XXX: how does this work in GNUTLS? */
+#ifndef HAVE_GNUTLS_GNUTLS_H
 static RSA *
 tls_tmp_rsa_cb( SSL *ssl, int is_export, int key_length )
 {
@@ -1636,6 +1813,7 @@
 	}
 	return tmp_rsa;
 }
+#endif
 
 static int
 tls_seed_PRNG( const char *randfile )
diff -uNr -x build openldap2-2.1.17.orig/libraries/libldap_r/Makefile.in openldap2-2.1.17/libraries/libldap_r/Makefile.in
--- openldap2-2.1.17.orig/libraries/libldap_r/Makefile.in	2003-06-17 20:31:13.000000000 -0500
+++ openldap2-2.1.17/libraries/libldap_r/Makefile.in	2003-06-28 21:29:05.000000000 -0500
@@ -18,7 +18,8 @@
 	getdn.c getentry.c getattr.c getvalues.c addentry.c \
 	request.c os-ip.c url.c sortctrl.c vlvctrl.c \
 	init.c options.c print.c string.c util-int.c schema.c \
-	charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c
+	charray.c tls.c gnutls.c os-local.c dnssrv.c utf-8.c \
+	utf-8-conv.c
 SRCS	= threads.c rdwr.c tpool.c \
 	thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \
 	thr_pth.c thr_stub.c
@@ -33,7 +34,8 @@
 	getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
 	request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
 	init.lo options.lo print.lo string.lo util-int.lo schema.lo \
-	charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo
+	charray.lo tls.lo gnutls.lo os-local.lo dnssrv.lo utf-8.lo \
+	utf-8-conv.lo
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
diff -uNr -x build openldap2-2.1.17.orig/servers/slapd/schema_init.c openldap2-2.1.17/servers/slapd/schema_init.c
--- openldap2-2.1.17.orig/servers/slapd/schema_init.c	2003-02-26 09:17:49.000000000 -0600
+++ openldap2-2.1.17/servers/slapd/schema_init.c	2003-06-28 21:59:13.000000000 -0500
@@ -3605,14 +3605,20 @@
 }
 
 #ifdef HAVE_TLS
+#ifdef HAVE_GNUTLS_GNUTLS_H
+#include <gnutls/gnutls.h>
+#include "ldap_pvt_gnutls.h"
+#else
 #include <openssl/x509.h>
 #include <openssl/err.h>
+#endif
 
 /*
  * Next function returns a string representation of a ASN1_INTEGER.
  * It works for unlimited lengths.
  */
 
+#ifndef HAVE_GNUTLS_GNUTLS_H
 static struct berval *
 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
 {
@@ -3673,6 +3679,8 @@
 
 	return ber_str2bv( p, 0, 1, bv );
 }
+#endif
+
 
 /*
  * Given a certificate in DER format, extract the corresponding
@@ -3688,6 +3696,9 @@
 	struct berval serial;
 	struct berval issuer_dn;
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	return LDAP_INVALID_SYNTAX;
+#else
 	xcert = d2i_X509(NULL, &p, in->bv_len);
 	if ( !xcert ) {
 #ifdef NEW_LOGGING
@@ -3740,6 +3751,7 @@
 	ber_memfree(issuer_dn.bv_val);
 
 	return LDAP_SUCCESS;
+#endif /* HAVE_GNUTLS_GNUTLS_H */
 }
 
 static int
@@ -3807,6 +3819,9 @@
 	struct berval asserted_issuer_dn;
 	int ret;
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	return LDAP_INVALID_SYNTAX;
+#else
 	xcert = d2i_X509(NULL, &p, value->bv_len);
 	if ( !xcert ) {
 #ifdef NEW_LOGGING
@@ -3871,6 +3886,7 @@
 	ber_memfree(asserted_issuer_dn.bv_val);
 
 	return ret;
+#endif /* HAVE_GNUTLS_GNUTLS_H */
 }
 
 /* 
@@ -3900,6 +3916,9 @@
 		/* empty -- just count them */
 	}
 
+#ifdef HAVE_GNUTLS_GNUTLS_H
+	return LDAP_INVALID_SYNTAX;
+#else
 	keys = ch_malloc( sizeof( struct berval ) * (i+1) );
 
 	for( i=0; values[i].bv_val != NULL; i++ ) {
@@ -3939,6 +3958,7 @@
 	keys[i].bv_val = NULL;
 	*keysp = keys;
 	return LDAP_SUCCESS;
+#endif /* HAVE_GNUTLS_GNUTLS_H */
 }
 
 /* Index generation function */
diff -uNr openldap2-2.1.17.orig/build/install-sh openldap2-2.1.17/build/install-sh
--- openldap2-2.1.17.orig/build/install-sh	1969-12-31 18:00:00.000000000 -0600
+++ openldap2-2.1.17/build/install-sh	2003-06-22 20:00:02.000000000 -0500
@@ -0,0 +1,269 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+#
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS=' 	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
