Remainder of SSL purpose and trust code: trust and purpose setting in
SSL_CTX and SSL, functions to set them and defaults if no values set.
diff --git a/CHANGES b/CHANGES
index fa00300..8b033f4 100644
--- a/CHANGES
+++ b/CHANGES
@@ -17,9 +17,8 @@
      when the X509_STORE_CTX structure is set up) and checks the pathlength.
 
      There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour:
-     this is because when it is finally working it will reject chains with
-     invalid extensions whereas every previous version of OpenSSL and SSLeay
-     made no checks at all.
+     this is because it will reject chains with invalid extensions whereas
+     every previous version of OpenSSL and SSLeay made no checks at all.
 
      Trust code: checks the root CA for the relevant trust settings. Trust
      settings have an initial value consistent with the verify purpose: e.g.
@@ -32,6 +31,10 @@
      which should be used for version portability: especially since the
      verify structure is likely to change more often now.
 
+     SSL integration. Add purpose and trust to SSL_CTX and SSL and functions
+     to set them. If not set then assume SSL clients will verify SSL servers
+     and vice versa.
+
      Two new options to the verify program: -untrusted allows a set of
      untrusted certificates to be passed in and -purpose which sets the
      intended purpose of the certificate. If a purpose is set then the
diff --git a/apps/s_client.c b/apps/s_client.c
index 60a8728..0afd790 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -740,6 +740,7 @@
 	if (ctx != NULL) SSL_CTX_free(ctx);
 	if (cbuf != NULL) { memset(cbuf,0,BUFSIZZ); Free(cbuf); }
 	if (sbuf != NULL) { memset(sbuf,0,BUFSIZZ); Free(sbuf); }
+	X509_cleanup();
 	if (bio_c_out != NULL)
 		{
 		BIO_free(bio_c_out);
diff --git a/apps/s_server.c b/apps/s_server.c
index a33e0ff..7a3a028 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -718,6 +718,7 @@
 	ret=0;
 end:
 	if (ctx != NULL) SSL_CTX_free(ctx);
+	X509_cleanup();
 	if (bio_s_out != NULL)
 		{
 		BIO_free(bio_s_out);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 11f462f..2668bd1 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -732,9 +732,9 @@
 	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
 	}
 
-void X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
 	{
-	ctx->trust = trust;
+	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
 	}
 
 /* This function is used to set the X509_STORE_CTX purpose and trust
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index 822d9c7..3e97df1 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -350,7 +350,7 @@
 void	X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
 void	X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
-void X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
 				int purpose, int trust);
 
diff --git a/ssl/Makefile.ssl b/ssl/Makefile.ssl
index 0eb0b0c..04ed4b3 100644
--- a/ssl/Makefile.ssl
+++ b/ssl/Makefile.ssl
@@ -537,24 +537,26 @@
 ssl_cert.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 ssl_cert.o: ../include/openssl/blowfish.h ../include/openssl/bn.h
 ssl_cert.o: ../include/openssl/buffer.h ../include/openssl/cast.h
-ssl_cert.o: ../include/openssl/comp.h ../include/openssl/crypto.h
-ssl_cert.o: ../include/openssl/des.h ../include/openssl/dh.h
-ssl_cert.o: ../include/openssl/dsa.h ../include/openssl/e_os.h
-ssl_cert.o: ../include/openssl/e_os.h ../include/openssl/e_os2.h
-ssl_cert.o: ../include/openssl/err.h ../include/openssl/evp.h
-ssl_cert.o: ../include/openssl/idea.h ../include/openssl/lhash.h
-ssl_cert.o: ../include/openssl/md2.h ../include/openssl/md5.h
-ssl_cert.o: ../include/openssl/mdc2.h ../include/openssl/objects.h
-ssl_cert.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-ssl_cert.o: ../include/openssl/pem.h ../include/openssl/pem2.h
-ssl_cert.o: ../include/openssl/pkcs7.h ../include/openssl/rc2.h
-ssl_cert.o: ../include/openssl/rc4.h ../include/openssl/rc5.h
-ssl_cert.o: ../include/openssl/ripemd.h ../include/openssl/rsa.h
-ssl_cert.o: ../include/openssl/safestack.h ../include/openssl/sha.h
-ssl_cert.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
-ssl_cert.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
-ssl_cert.o: ../include/openssl/stack.h ../include/openssl/tls1.h
-ssl_cert.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h ssl_locl.h
+ssl_cert.o: ../include/openssl/comp.h ../include/openssl/conf.h
+ssl_cert.o: ../include/openssl/crypto.h ../include/openssl/des.h
+ssl_cert.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+ssl_cert.o: ../include/openssl/e_os.h ../include/openssl/e_os.h
+ssl_cert.o: ../include/openssl/e_os2.h ../include/openssl/err.h
+ssl_cert.o: ../include/openssl/evp.h ../include/openssl/idea.h
+ssl_cert.o: ../include/openssl/lhash.h ../include/openssl/md2.h
+ssl_cert.o: ../include/openssl/md5.h ../include/openssl/mdc2.h
+ssl_cert.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+ssl_cert.o: ../include/openssl/opensslv.h ../include/openssl/pem.h
+ssl_cert.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
+ssl_cert.o: ../include/openssl/rc2.h ../include/openssl/rc4.h
+ssl_cert.o: ../include/openssl/rc5.h ../include/openssl/ripemd.h
+ssl_cert.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
+ssl_cert.o: ../include/openssl/sha.h ../include/openssl/ssl.h
+ssl_cert.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+ssl_cert.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+ssl_cert.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ssl_cert.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h
+ssl_cert.o: ssl_locl.h
 ssl_ciph.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 ssl_ciph.o: ../include/openssl/blowfish.h ../include/openssl/bn.h
 ssl_ciph.o: ../include/openssl/buffer.h ../include/openssl/cast.h
@@ -619,24 +621,25 @@
 ssl_lib.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 ssl_lib.o: ../include/openssl/blowfish.h ../include/openssl/bn.h
 ssl_lib.o: ../include/openssl/buffer.h ../include/openssl/cast.h
-ssl_lib.o: ../include/openssl/comp.h ../include/openssl/crypto.h
-ssl_lib.o: ../include/openssl/des.h ../include/openssl/dh.h
-ssl_lib.o: ../include/openssl/dsa.h ../include/openssl/e_os.h
-ssl_lib.o: ../include/openssl/e_os2.h ../include/openssl/err.h
-ssl_lib.o: ../include/openssl/evp.h ../include/openssl/idea.h
-ssl_lib.o: ../include/openssl/lhash.h ../include/openssl/md2.h
-ssl_lib.o: ../include/openssl/md5.h ../include/openssl/mdc2.h
-ssl_lib.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
-ssl_lib.o: ../include/openssl/opensslv.h ../include/openssl/pem.h
-ssl_lib.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
-ssl_lib.o: ../include/openssl/rc2.h ../include/openssl/rc4.h
-ssl_lib.o: ../include/openssl/rc5.h ../include/openssl/ripemd.h
-ssl_lib.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
-ssl_lib.o: ../include/openssl/sha.h ../include/openssl/ssl.h
-ssl_lib.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
-ssl_lib.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
-ssl_lib.o: ../include/openssl/tls1.h ../include/openssl/x509.h
-ssl_lib.o: ../include/openssl/x509_vfy.h ssl_locl.h
+ssl_lib.o: ../include/openssl/comp.h ../include/openssl/conf.h
+ssl_lib.o: ../include/openssl/crypto.h ../include/openssl/des.h
+ssl_lib.o: ../include/openssl/dh.h ../include/openssl/dsa.h
+ssl_lib.o: ../include/openssl/e_os.h ../include/openssl/e_os2.h
+ssl_lib.o: ../include/openssl/err.h ../include/openssl/evp.h
+ssl_lib.o: ../include/openssl/idea.h ../include/openssl/lhash.h
+ssl_lib.o: ../include/openssl/md2.h ../include/openssl/md5.h
+ssl_lib.o: ../include/openssl/mdc2.h ../include/openssl/objects.h
+ssl_lib.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
+ssl_lib.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+ssl_lib.o: ../include/openssl/pkcs7.h ../include/openssl/rc2.h
+ssl_lib.o: ../include/openssl/rc4.h ../include/openssl/rc5.h
+ssl_lib.o: ../include/openssl/ripemd.h ../include/openssl/rsa.h
+ssl_lib.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+ssl_lib.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
+ssl_lib.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
+ssl_lib.o: ../include/openssl/stack.h ../include/openssl/tls1.h
+ssl_lib.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h
+ssl_lib.o: ../include/openssl/x509v3.h ssl_locl.h
 ssl_rsa.o: ../include/openssl/asn1.h ../include/openssl/bio.h
 ssl_rsa.o: ../include/openssl/blowfish.h ../include/openssl/bn.h
 ssl_rsa.o: ../include/openssl/buffer.h ../include/openssl/cast.h
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 1b39f0d..96c5a93 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1009,6 +1009,12 @@
 SSL *	SSL_new(SSL_CTX *ctx);
 int	SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx,
 				   unsigned int sid_ctx_len);
+
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
+int SSL_set_purpose(SSL *s, int purpose);
+int SSL_CTX_set_trust(SSL_CTX *s, int trust);
+int SSL_set_trust(SSL *s, int trust);
+
 void	SSL_free(SSL *ssl);
 int 	SSL_accept(SSL *ssl);
 int 	SSL_connect(SSL *ssl);
@@ -1235,8 +1241,10 @@
 #define SSL_F_SSL_CREATE_CIPHER_LIST			 166
 #define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY			 168
 #define SSL_F_SSL_CTX_NEW				 169
+#define SSL_F_SSL_CTX_SET_PURPOSE			 226
 #define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT		 219
 #define SSL_F_SSL_CTX_SET_SSL_VERSION			 170
+#define SSL_F_SSL_CTX_SET_TRUST				 229
 #define SSL_F_SSL_CTX_USE_CERTIFICATE			 171
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1		 172
 #define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE	 220
@@ -1264,9 +1272,11 @@
 #define SSL_F_SSL_SET_CERT				 191
 #define SSL_F_SSL_SET_FD				 192
 #define SSL_F_SSL_SET_PKEY				 193
+#define SSL_F_SSL_SET_PURPOSE				 227
 #define SSL_F_SSL_SET_RFD				 194
 #define SSL_F_SSL_SET_SESSION				 195
 #define SSL_F_SSL_SET_SESSION_ID_CONTEXT		 218
+#define SSL_F_SSL_SET_TRUST				 228
 #define SSL_F_SSL_SET_WFD				 196
 #define SSL_F_SSL_SHUTDOWN				 224
 #define SSL_F_SSL_UNDEFINED_FUNCTION			 197
@@ -1348,6 +1358,8 @@
 #define SSL_R_HTTP_REQUEST				 156
 #define SSL_R_INTERNAL_ERROR				 157
 #define SSL_R_INVALID_CHALLENGE_LENGTH			 158
+#define SSL_R_INVALID_PURPOSE				 278
+#define SSL_R_INVALID_TRUST				 279
 #define SSL_R_LENGTH_MISMATCH				 159
 #define SSL_R_LENGTH_TOO_SHORT				 160
 #define SSL_R_LIBRARY_BUG				 274
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index a695d04..3eda14a 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -124,6 +124,7 @@
 #include <openssl/objects.h>
 #include <openssl/bio.h>
 #include <openssl/pem.h>
+#include <openssl/x509v3.h>
 #include "ssl_locl.h"
 
 int SSL_get_ex_data_X509_STORE_CTX_idx(void)
@@ -432,6 +433,15 @@
 		X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
 	X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),
 		(char *)s);
+	/* We need to set the verify purpose. The purpose can be determined by
+	 * the context: if its a server it will verify SSL client certificates
+	 * or vice versa.
+         */
+
+	if(s->server) i = X509_PURPOSE_SSL_CLIENT;
+	else i = X509_PURPOSE_SSL_SERVER;
+
+	X509_STORE_CTX_purpose_inherit(&ctx, i, s->purpose, s->trust);
 
 	if (s->ctx->app_verify_callback != NULL)
 		i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
@@ -542,7 +552,7 @@
 	return(add_client_CA(&(ctx->client_CA),x));
 	}
 
-static int name_cmp(X509_NAME **a,X509_NAME **b)
+static int xname_cmp(X509_NAME **a,X509_NAME **b)
 	{
 	return(X509_NAME_cmp(*a,*b));
 	}
@@ -564,7 +574,7 @@
 	STACK_OF(X509_NAME) *ret,*sk;
 
 	ret=sk_X509_NAME_new(NULL);
-	sk=sk_X509_NAME_new(name_cmp);
+	sk=sk_X509_NAME_new(xname_cmp);
 
 	in=BIO_new(BIO_s_file_internal());
 
@@ -625,7 +635,7 @@
     int ret=1;
     int (*oldcmp)(X509_NAME **a, X509_NAME **b);
 
-    oldcmp=sk_X509_NAME_set_cmp_func(stack,name_cmp);
+    oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp);
 
     in=BIO_new(BIO_s_file_internal());
 
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 3ddc805..7c61165 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -140,8 +140,10 @@
 {ERR_PACK(0,SSL_F_SSL_CREATE_CIPHER_LIST,0),	"SSL_CREATE_CIPHER_LIST"},
 {ERR_PACK(0,SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,0),	"SSL_CTX_check_private_key"},
 {ERR_PACK(0,SSL_F_SSL_CTX_NEW,0),	"SSL_CTX_new"},
+{ERR_PACK(0,SSL_F_SSL_CTX_SET_PURPOSE,0),	"SSL_CTX_set_purpose"},
 {ERR_PACK(0,SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,0),	"SSL_CTX_set_session_id_context"},
 {ERR_PACK(0,SSL_F_SSL_CTX_SET_SSL_VERSION,0),	"SSL_CTX_set_ssl_version"},
+{ERR_PACK(0,SSL_F_SSL_CTX_SET_TRUST,0),	"SSL_CTX_set_trust"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE,0),	"SSL_CTX_use_certificate"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,0),	"SSL_CTX_use_certificate_ASN1"},
 {ERR_PACK(0,SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,0),	"SSL_CTX_use_certificate_chain_file"},
@@ -169,9 +171,11 @@
 {ERR_PACK(0,SSL_F_SSL_SET_CERT,0),	"SSL_SET_CERT"},
 {ERR_PACK(0,SSL_F_SSL_SET_FD,0),	"SSL_set_fd"},
 {ERR_PACK(0,SSL_F_SSL_SET_PKEY,0),	"SSL_SET_PKEY"},
+{ERR_PACK(0,SSL_F_SSL_SET_PURPOSE,0),	"SSL_set_purpose"},
 {ERR_PACK(0,SSL_F_SSL_SET_RFD,0),	"SSL_set_rfd"},
 {ERR_PACK(0,SSL_F_SSL_SET_SESSION,0),	"SSL_set_session"},
 {ERR_PACK(0,SSL_F_SSL_SET_SESSION_ID_CONTEXT,0),	"SSL_set_session_id_context"},
+{ERR_PACK(0,SSL_F_SSL_SET_TRUST,0),	"SSL_set_trust"},
 {ERR_PACK(0,SSL_F_SSL_SET_WFD,0),	"SSL_set_wfd"},
 {ERR_PACK(0,SSL_F_SSL_SHUTDOWN,0),	"SSL_shutdown"},
 {ERR_PACK(0,SSL_F_SSL_UNDEFINED_FUNCTION,0),	"SSL_UNDEFINED_FUNCTION"},
@@ -256,6 +260,8 @@
 {SSL_R_HTTP_REQUEST                      ,"http request"},
 {SSL_R_INTERNAL_ERROR                    ,"internal error"},
 {SSL_R_INVALID_CHALLENGE_LENGTH          ,"invalid challenge length"},
+{SSL_R_INVALID_PURPOSE                   ,"invalid purpose"},
+{SSL_R_INVALID_TRUST                     ,"invalid trust"},
 {SSL_R_LENGTH_MISMATCH                   ,"length mismatch"},
 {SSL_R_LENGTH_TOO_SHORT                  ,"length too short"},
 {SSL_R_LIBRARY_BUG                       ,"library bug"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 9dd6860..3bd8d15 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -61,6 +61,7 @@
 #include <stdio.h>
 #include <openssl/objects.h>
 #include <openssl/lhash.h>
+#include <openssl/x509v3.h>
 #include "ssl_locl.h"
 
 char *SSL_version_str=OPENSSL_VERSION_TEXT;
@@ -264,6 +265,46 @@
     return 1;
     }
 
+int SSL_CTX_set_purpose(SSL_CTX *s, int purpose)
+{
+	if(X509_PURPOSE_get_by_id(purpose) == -1) {
+		SSLerr(SSL_F_SSL_CTX_SET_PURPOSE, SSL_R_INVALID_PURPOSE);
+		return 0;
+	}
+	s->purpose = purpose;
+	return 1;
+}
+
+int SSL_set_purpose(SSL *s, int purpose)
+{
+	if(X509_PURPOSE_get_by_id(purpose) == -1) {
+		SSLerr(SSL_F_SSL_SET_PURPOSE, SSL_R_INVALID_PURPOSE);
+		return 0;
+	}
+	s->purpose = purpose;
+	return 1;
+}
+	
+int SSL_CTX_set_trust(SSL_CTX *s, int trust)
+{
+	if(X509_TRUST_get_by_id(trust) == -1) {
+		SSLerr(SSL_F_SSL_CTX_SET_TRUST, SSL_R_INVALID_TRUST);
+		return 0;
+	}
+	s->trust = trust;
+	return 1;
+}
+
+int SSL_set_trust(SSL *s, int trust)
+{
+	if(X509_TRUST_get_by_id(trust) == -1) {
+		SSLerr(SSL_F_SSL_SET_TRUST, SSL_R_INVALID_TRUST);
+		return 0;
+	}
+	s->trust = trust;
+	return 1;
+}
+
 void SSL_free(SSL *s)
 	{
 	int i;
@@ -1079,6 +1120,12 @@
 	ret->extra_certs=NULL;
 	ret->comp_methods=SSL_COMP_get_compression_methods();
 
+	/* Initialise X509 tables: otherwise some certificate operations
+	 * wont work. This is a non op if called more than once.
+	 */
+
+	X509_init();
+
 	return(ret);
 err:
 	SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
diff --git a/util/ssleay.num b/util/ssleay.num
index 8121738..ee95837 100755
--- a/util/ssleay.num
+++ b/util/ssleay.num
@@ -215,3 +215,7 @@
 sk_SSL_COMP_sort                        233
 sk_SSL_CIPHER_sort                      234
 SSL_CTX_set_default_passwd_cb_userdata  235
+SSL_set_purpose                         236
+SSL_CTX_set_trust                       237
+SSL_CTX_set_purpose                     238
+SSL_set_trust                           239