Allow extensions to be added to certificate requests, update the sample
config file (change RAW to DER).
diff --git a/CHANGES b/CHANGES
index a3a8f28..348252e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 1999]
 
+  *) Allow certificate extensions to be added to certificate requests. These
+     are specified in a 'req_extensions' option of the req section of the
+     config file. They can be printed out with the -text option to req but
+     are otherwise ignored at present.
+     [Steve Henson]
+
   *) Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first data
      read consists of only the final block it would not decrypted because
      EVP_CipherUpdate() would correctly report zero bytes had been decrypted.
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index d70dd25..8d044fb 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -86,6 +86,8 @@
 attributes		= req_attributes
 x509_extensions	= v3_ca	# The extentions to add to the self signed cert
 
+# req_extensions = v3_req # The extensions to add to a certificate request
+
 [ req_distinguished_name ]
 countryName			= Country Name (2 letter code)
 countryName_default		= AU
@@ -170,8 +172,16 @@
 #nsCaPolicyUrl
 #nsSslServerName
 
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
 [ v3_ca ]
 
+
 # Extensions for a typical CA
 
 
@@ -200,10 +210,11 @@
 # Copy issuer details
 # issuerAltName=issuer:copy
 
-# RAW DER hex encoding of an extension: beware experts only!
-# 1.2.3.5=RAW:02:03
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
 # You can even override a supported extension:
-# basicConstraints= critical, RAW:30:03:01:01:FF
+# basicConstraints= critical, DER:30:03:01:01:FF
 
 [ crl_ext ]
 
diff --git a/apps/req.c b/apps/req.c
index 463ac15..fa8f733 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -82,6 +82,7 @@
 #define DISTINGUISHED_NAME	"distinguished_name"
 #define ATTRIBUTES	"attributes"
 #define V3_EXTENSIONS	"x509_extensions"
+#define REQ_EXTENSIONS	"req_extensions"
 
 #define DEFAULT_KEY_LENGTH	512
 #define MIN_KEY_LENGTH		384
@@ -142,6 +143,7 @@
 	int nodes=0,kludge=0;
 	char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
 	char *extensions = NULL;
+	char *req_exts = NULL;
 	EVP_CIPHER *cipher=NULL;
 	int modulus=0;
 	char *p;
@@ -438,6 +440,20 @@
 		}
 	}
 
+	req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
+	if(req_exts) {
+		/* Check syntax of file */
+		X509V3_CTX ctx;
+		X509V3_set_ctx_test(&ctx);
+		X509V3_set_conf_lhash(&ctx, req_conf);
+		if(!X509V3_EXT_add_conf(req_conf, &ctx, req_exts, NULL)) {
+			BIO_printf(bio_err,
+			 "Error Loading request extension section %s\n",
+								req_exts);
+			goto end;
+		}
+	}
+
 	in=BIO_new(BIO_s_file());
 	out=BIO_new(BIO_s_file());
 	if ((in == NULL) || (out == NULL))
@@ -677,6 +693,22 @@
 			}
 		else
 			{
+			X509V3_CTX ext_ctx;
+
+			/* Set up V3 context struct */
+
+			X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
+			X509V3_set_conf_lhash(&ext_ctx, req_conf);
+
+			/* Add extensions */
+			if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf, 
+				 	&ext_ctx, req_exts, req))
+			    {
+			    BIO_printf(bio_err,
+				       "Error Loading extension section %s\n",
+				       req_exts);
+			    goto end;
+			    }
 			if (!(i=X509_REQ_sign(req,pkey,digest)))
 				goto end;
 			}
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
index f19bb3a..d092fe9 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509v3/v3_conf.c
@@ -220,7 +220,7 @@
 	return 1;
 }
 
-/* Create a generic extension: for now just handle RAW type */
+/* Create a generic extension: for now just handle DER type */
 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
 	     int crit, int type)
 {
@@ -302,6 +302,30 @@
 	return 1;
 }
 
+/* Add extensions to certificate request */
+
+int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section,
+	     X509_REQ *req)
+{
+	X509_EXTENSION *ext;
+	STACK_OF(X509_EXTENSION) *extlist = NULL;
+	STACK_OF(CONF_VALUE) *nval;
+	CONF_VALUE *val;	
+	int i;
+	if(!(nval = CONF_get_section(conf, section))) return 0;
+	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+		val = sk_CONF_VALUE_value(nval, i);
+		if(!(ext = X509V3_EXT_conf(conf, ctx, val->name, val->value)))
+								return 0;
+		if(!extlist) extlist = sk_X509_EXTENSION_new_null();
+		sk_X509_EXTENSION_push(extlist, ext);
+	}
+	if(req) i = X509_REQ_add_extensions(req, extlist);
+	else i = 1;
+	sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
+	return i;
+}
+
 /* Config database functions */
 
 char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index 4eb04a5..af0e62f 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -386,6 +386,7 @@
 X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value);
 X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value);
 int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
 int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
 int X509V3_add_value_bool_nf(char *name, int asn1_bool,
 						STACK_OF(CONF_VALUE) **extlist);