Redo the way 'req' and 'ca' add objects: add support for oid_section.
diff --git a/CHANGES b/CHANGES
index c2ef7bf..0af7ea0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,11 @@
 
  Changes between 0.9.1c and 0.9.2
 
+  *) Dump the old yucky req code that tried (and failed) to allow raw OIDs
+     to be added. Now both 'req' and 'ca' can use new objects defined in the
+     config file.
+     [Steve Henson]
+
   *) Add cool BIO that does syslog (or event log on NT).
      [Arne Ansper <arne@ats.cyber.ee>, integrated by Ben Laurie]
 
diff --git a/apps/ca.c b/apps/ca.c
index 76bbcbc..6f3b1a8 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -155,6 +155,7 @@
 #endif
 
 #ifndef NOPROTO
+static int add_oid_section(LHASH *conf);
 static void lookup_fail(char *name,char *tag);
 static int MS_CALLBACK key_callback(char *buf,int len,int verify);
 static unsigned long index_serial_hash(char **a);
@@ -181,6 +182,7 @@
 	LHASH *conf);
 static int check_time_format(char *str);
 #else
+static int add_oid_section();
 static void lookup_fail();
 static int MS_CALLBACK key_callback();
 static unsigned long index_serial_hash();
@@ -453,6 +455,10 @@
 				}
 			}
 		}
+		if(!add_oid_section(conf)) {
+			ERR_print_errors(bio_err);
+			goto err;
+		}
 
 	in=BIO_new(BIO_s_file());
 	out=BIO_new(BIO_s_file());
@@ -1044,22 +1050,23 @@
 	/*****************************************************************/
 	ret=0;
 err:
-	if (hex != NULL) BIO_free(hex);
-	if (Cout != NULL) BIO_free(Cout);
-	if (Sout != NULL) BIO_free(Sout);
-	if (out != NULL) BIO_free(out);
-	if (in != NULL) BIO_free(in);
+	BIO_free(hex);
+	BIO_free(Cout);
+	BIO_free(Sout);
+	BIO_free(out);
+	BIO_free(in);
 
-	if (cert_sk != NULL) sk_pop_free(cert_sk,X509_free);
+	sk_pop_free(cert_sk,X509_free);
 
 	if (ret) ERR_print_errors(bio_err);
-	if (serial != NULL) BN_free(serial);
-	if (db != NULL) TXT_DB_free(db);
-	if (pkey != NULL) EVP_PKEY_free(pkey);
-	if (x509 != NULL) X509_free(x509);
-	if (crl != NULL) X509_CRL_free(crl);
-	if (conf != NULL) CONF_free(conf);
+	BN_free(serial);
+	TXT_DB_free(db);
+	EVP_PKEY_free(pkey);
+	X509_free(x509);
+	X509_CRL_free(crl);
+	CONF_free(conf);
 	X509V3_EXT_cleanup();
+	OBJ_cleanup();
 	EXIT(ret);
 	}
 
@@ -2009,3 +2016,25 @@
 	return(ASN1_UTCTIME_check(&tm));
 	}
 
+static int add_oid_section(conf)
+LHASH *conf;
+{	
+	char *p;
+	STACK *sktmp;
+	CONF_VALUE *cnf;
+	int i;
+	if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1;
+	if(!(sktmp = CONF_get_section(conf, p))) {
+		BIO_printf(bio_err, "problem loading oid section %s\n", p);
+		return 0;
+	}
+	for(i = 0; i < sk_num(sktmp); i++) {
+		cnf = (CONF_VALUE *)sk_value(sktmp, i);
+		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+			BIO_printf(bio_err, "problem creating object %s=%s\n",
+							 cnf->name, cnf->value);
+			return 0;
+		}
+	}
+	return 1;
+}
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index 7dee643..49cff56 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -5,6 +5,15 @@
 
 RANDFILE		= $ENV::HOME/.rnd
 oid_file		= $ENV::HOME/.oid
+oid_section		= new_oids
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
 
 ####################################################################
 [ ca ]
@@ -92,7 +101,7 @@
 emailAddress			= Email Address
 emailAddress_max		= 40
 
-SET-ex3				= SET extension number 3
+# SET-ex3			= SET extension number 3
 
 [ req_attributes ]
 challengePassword		= A challenge password
diff --git a/apps/req.c b/apps/req.c
index b2c1bb2..9a100ae 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -115,12 +115,16 @@
 	int nid,int min,int max);
 static void MS_CALLBACK req_cb(int p,int n,char *arg);
 static int req_fix_data(int nid,int *type,int len,int min,int max);
+static int check_end(char *str, char *end);
+static int add_oid_section(LHASH *conf);
 #else
 static int make_REQ();
 static int add_attribute_object();
 static int add_DN_object();
 static void MS_CALLBACK req_cb();
 static int req_fix_data();
+static int check_end();
+static int add_oid_section();
 #endif
 
 #ifndef MONOLITH
@@ -423,6 +427,7 @@
 				}
 			}
 		}
+		if(!add_oid_section(req_conf)) goto end;
 
 	if ((md_alg == NULL) &&
 		((p=CONF_get_string(req_conf,SECTION,"default_md")) != NULL))
@@ -800,11 +805,13 @@
 		ERR_print_errors(bio_err);
 		}
 	if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf);
-	if (in != NULL) BIO_free(in);
-	if (out != NULL) BIO_free(out);
-	if (pkey != NULL) EVP_PKEY_free(pkey);
-	if (req != NULL) X509_REQ_free(req);
-	if (x509ss != NULL) X509_free(x509ss);
+	BIO_free(in);
+	BIO_free(out);
+	EVP_PKEY_free(pkey);
+	X509_REQ_free(req);
+	X509_free(x509ss);
+	X509V3_EXT_cleanup();
+	OBJ_cleanup();
 #ifndef NO_DSA
 	if (dsa_params != NULL) DSA_free(dsa_params);
 #endif
@@ -816,7 +823,7 @@
 EVP_PKEY *pkey;
 int attribs;
 	{
-	int ret=0,i,j;
+	int ret=0,i;
 	unsigned char *p,*q;
 	X509_REQ_INFO *ri;
 	char buf[100];
@@ -876,42 +883,18 @@
 			v=(CONF_VALUE *)sk_value(sk,i);
 			p=q=NULL;
 			type=v->name;
-			/* Allow for raw OIDs */
-			/* [n.mm.ooo.ppp] */
-			for (j=0; type[j] != '\0'; j++)
-				{
-				if (	(type[j] == ':') ||
-					(type[j] == ',') ||
-					(type[j] == '.'))
-					p=(unsigned char *)&(type[j+1]);
-				if (type[j] == '[')
-					{
-					p=(unsigned char *)&(type[j+1]);
-					for (j++; type[j] != '\0'; j++)
-						if (type[j] == ']')
-							{
-							q=(unsigned char *)&(type[j]);
-							break;
-							}
-					break;
-					}
-				}
-			if (p != NULL)
-				type=(char *)p;
-			if ((nid=OBJ_txt2nid(type)) == NID_undef)
-				{
-				/* Add a new one if possible */
-				if ((p != NULL) && (q != NULL) && (*q == ']'))
-					{
-					*q='\0';
-					nid=OBJ_create((char *)p,NULL,NULL);
-					*q=']';
-					if (nid == NID_undef) goto start;
-					}
-				else
-					goto start;
-				}
-
+			if(!check_end(type,"_min") || !check_end(type,"_max") ||
+				!check_end(type,"_default") ||
+					 !check_end(type,"_value")) continue;
+			/* Skip past any leading X. X: X, etc to allow for
+			 * multiple instances 
+			 */
+			for(p = v->name; *p ; p++) 
+				if ((*p != ':') || (*p != ',') ||
+							 (*p != '.')) break;
+			if (*p) type=(char *)p;
+			/* If OBJ not recognised ignore it */
+			if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
 			sprintf(buf,"%s_default",v->name);
 			if ((def=CONF_get_string(req_conf,tmp,buf)) == NULL)
 				def="";
@@ -1194,3 +1177,41 @@
 		}
 	return(1);
 	}
+
+/* Check if the end of a string matches 'end' */
+static int check_end(str, end)
+char *str;
+char *end;
+{
+	int elen, slen;	
+	char *tmp;
+	elen = strlen(end);
+	slen = strlen(str);
+	if(elen > slen) return 1;
+	tmp = str + slen - elen;
+fprintf(stderr, "Matching %s, %s %s\n", str, end, tmp);
+	return strcmp(tmp, end);
+}
+
+static int add_oid_section(conf)
+LHASH *conf;
+{	
+	char *p;
+	STACK *sktmp;
+	CONF_VALUE *cnf;
+	int i;
+	if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1;
+	if(!(sktmp = CONF_get_section(conf, p))) {
+		BIO_printf(bio_err, "problem loading oid section %s\n", p);
+		return 0;
+	}
+	for(i = 0; i < sk_num(sktmp); i++) {
+		cnf = (CONF_VALUE *)sk_value(sktmp, i);
+		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
+			BIO_printf(bio_err, "problem creating object %s=%s\n",
+							 cnf->name, cnf->value);
+			return 0;
+		}
+	}
+	return 1;
+}