diff -ur openssl-orig/apps/ca.c openssl-work/apps/ca.c
--- openssl-orig/apps/ca.c	2005-09-30 18:47:15.000000000 +0200
+++ openssl-work/apps/ca.c	2006-12-27 22:30:15.000000000 +0100
@@ -176,6 +176,8 @@
 " -batch          - Don't ask questions\n",
 " -msie_hack      - msie modifications to handle all those universal strings\n",
 " -revoke file    - Revoke a certificate (given in file)\n",
+" -suspend file   - Suspend a certificate (given in file)\n",
+" -reinstate file - Reinstate a certificate (given in file)\n",
 " -subj arg       - Use arg instead of request's subject\n",
 " -utf8           - input characters are UTF8 (default ASCII)\n",
 " -multivalue-rdn - enable support for multivalued RDNs\n",
@@ -225,6 +227,8 @@
 	unsigned long certopt, unsigned long nameopt, int default_op,
 	int ext_copy, int selfsign);
 static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
+static int do_suspend(X509 *x509, CA_DB *db);
+static int do_reinstate(X509 *x509, CA_DB *db);
 static int get_certificate_status(const char *ser_status, CA_DB *db);
 static int do_updatedb(CA_DB *db);
 static int check_time_format(char *str);
@@ -256,6 +260,8 @@
 	int verbose=0;
 	int gencrl=0;
 	int dorevoke=0;
+	int dosuspend=0;
+	int doreinstate=0;
 	int doupdatedb=0;
 	long crldays=0;
 	long crlhours=0;
@@ -482,6 +488,18 @@
 			infile= *(++argv);
 			dorevoke=1;
 			}
+		else if (strcmp(*argv,"-suspend") == 0)
+			{
+			if (--argc < 1) goto bad;
+			infile= *(++argv);
+			dosuspend=1;
+			}
+		else if (strcmp(*argv,"-reinstate") == 0)
+			{
+			if (--argc < 1) goto bad;
+			infile= *(++argv);
+			doreinstate=1;
+			}
 		else if (strcmp(*argv,"-extensions") == 0)
 			{
 			if (--argc < 1) goto bad;
@@ -1472,13 +1490,13 @@
 
 		}
 	/*****************************************************************/
-	if (dorevoke)
-		{
+	if (dorevoke || dosuspend || doreinstate)
+		{
 		if (infile == NULL) 
 			{
 			BIO_printf(bio_err,"no input files\n");
 			goto err;
-			}
+			}
 		else
 			{
 			X509 *revcert;
@@ -1486,7 +1504,20 @@
 				NULL, e, infile);
 			if (revcert == NULL)
 				goto err;
-			j=do_revoke(revcert,db, rev_type, rev_arg);
+
+			if (dorevoke)
+				{
+				j=do_revoke(revcert,db, rev_type, rev_arg);
+				}
+			else if (dosuspend)
+				{
+				j=do_suspend(revcert,db);
+				}
+			else if (doreinstate)
+				{
+				j=do_reinstate(revcert,db);
+				}
+
 			if (j <= 0) goto err;
 			X509_free(revcert);
 
@@ -1495,9 +1526,10 @@
 			if (!rotate_index(dbfile, "new", "old")) goto err;
 
 			BIO_printf(bio_err,"Data Base Updated\n"); 
-			}
-		}
+			}
+		}
 	/*****************************************************************/
+
 	ret=0;
 err:
 	if(tofree)
@@ -2518,6 +2550,99 @@
 	return(ok);
 	}
 
+
+static int do_suspend(X509 *x509, CA_DB *db)
+	{
+	return do_revoke(x509,db,REV_CRL_REASON,"certificateHold");
+	}
+
+	
+static int do_reinstate(X509 *x509, CA_DB *db)
+	{
+	char *row[DB_NUMBER],**rrow;
+	BIGNUM *bn = NULL;
+	int ok=-1,i;
+
+	for (i=0; i<DB_NUMBER; i++)
+		row[i]=NULL;
+	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
+	bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
+	if (BN_is_zero(bn))
+		row[DB_serial]=BUF_strdup("00");
+	else
+		row[DB_serial]=BN_bn2hex(bn);
+	BN_free(bn);
+	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
+		{
+		BIO_printf(bio_err,"Memory allocation failure\n");
+		goto err;
+		}
+
+	/* We have to lookup by serial number because name lookup
+	 * skips revoked certs
+ 	 */
+	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
+	if (rrow == NULL)
+		{
+		BIO_printf(bio_err,"ERROR:certificate with serial number %s not found\n",
+			   row[DB_name]);
+		goto err;
+		}
+	else if (index_name_cmp((const char **)row,(const char **)rrow))
+		{
+		BIO_printf(bio_err,"ERROR:name does not match %s\n",
+			   row[DB_name]);
+		goto err;
+		}
+	else if (rrow[DB_type][0]=='V')
+		{
+		BIO_printf(bio_err,"ERROR:Already reinstated, serial number %s\n",
+			   row[DB_serial]);
+		goto err;
+		}
+	else if (rrow[DB_type][0]=='E')
+		{
+		BIO_printf(bio_err,"ERROR:Cannot reinstate expired certificate, serial number %s\n",
+			   row[DB_serial]);
+		goto err;
+		}
+	else if (rrow[DB_type][0]=='R')
+		{
+		BIO_printf(bio_err,"Reinstating Certificate %s.\n", rrow[DB_serial]);
+
+		int reason_code = -1;
+		int ret = 0;
+		ASN1_OBJECT *hold = NULL;
+		ASN1_GENERALIZEDTIME *comp_time = NULL;
+		ASN1_TIME *revDate = NULL;
+		
+		ret = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, rrow[DB_rev_date]);
+		
+		if (ret == 0)
+			goto err;
+		
+		if (reason_code != 6)
+			{
+			BIO_printf(bio_err,"ERROR:Only revoked certificates with reason certificateHold can be reinstated, serial number %s\n",
+				   row[DB_serial]);
+			goto err;
+			}
+
+		rrow[DB_type][0]='V';
+		rrow[DB_type][1]='\0';
+		rrow[DB_rev_date] = NULL;
+		}
+	ok=1;
+err:
+	for (i=0; i<DB_NUMBER; i++)
+		{
+		if (row[i] != NULL) 
+			OPENSSL_free(row[i]);
+		}
+	return(ok);
+	}	
+
+
 static int get_certificate_status(const char *serial, CA_DB *db)
 	{
 	char *row[DB_NUMBER],**rrow;
