xref: /onnv-gate/usr/src/common/openssl/apps/ca.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* apps/ca.c */
2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3*0Sstevel@tonic-gate  * All rights reserved.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * This package is an SSL implementation written
6*0Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
7*0Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
10*0Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
11*0Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
12*0Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13*0Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
14*0Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
17*0Sstevel@tonic-gate  * the code are not to be removed.
18*0Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
19*0Sstevel@tonic-gate  * as the author of the parts of the library used.
20*0Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
21*0Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
24*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
25*0Sstevel@tonic-gate  * are met:
26*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
27*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
28*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
29*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
30*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
31*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
32*0Sstevel@tonic-gate  *    must display the following acknowledgement:
33*0Sstevel@tonic-gate  *    "This product includes cryptographic software written by
34*0Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
35*0Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
36*0Sstevel@tonic-gate  *    being used are not cryptographic related :-).
37*0Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
38*0Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
39*0Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40*0Sstevel@tonic-gate  *
41*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42*0Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*0Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*0Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*0Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*0Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*0Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*0Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*0Sstevel@tonic-gate  * SUCH DAMAGE.
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
54*0Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55*0Sstevel@tonic-gate  * copied and put under another distribution licence
56*0Sstevel@tonic-gate  * [including the GNU Public Licence.]
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate #include <stdio.h>
62*0Sstevel@tonic-gate #include <stdlib.h>
63*0Sstevel@tonic-gate #include <string.h>
64*0Sstevel@tonic-gate #include <ctype.h>
65*0Sstevel@tonic-gate #include <sys/types.h>
66*0Sstevel@tonic-gate #include <sys/stat.h>
67*0Sstevel@tonic-gate #include <openssl/conf.h>
68*0Sstevel@tonic-gate #include <openssl/bio.h>
69*0Sstevel@tonic-gate #include <openssl/err.h>
70*0Sstevel@tonic-gate #include <openssl/bn.h>
71*0Sstevel@tonic-gate #include <openssl/txt_db.h>
72*0Sstevel@tonic-gate #include <openssl/evp.h>
73*0Sstevel@tonic-gate #include <openssl/x509.h>
74*0Sstevel@tonic-gate #include <openssl/x509v3.h>
75*0Sstevel@tonic-gate #include <openssl/objects.h>
76*0Sstevel@tonic-gate #include <openssl/ocsp.h>
77*0Sstevel@tonic-gate #include <openssl/pem.h>
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WINDOWS
80*0Sstevel@tonic-gate #define strcasecmp _stricmp
81*0Sstevel@tonic-gate #else
82*0Sstevel@tonic-gate #  ifdef NO_STRINGS_H
83*0Sstevel@tonic-gate     int	strcasecmp();
84*0Sstevel@tonic-gate #  else
85*0Sstevel@tonic-gate #    include <strings.h>
86*0Sstevel@tonic-gate #  endif /* NO_STRINGS_H */
87*0Sstevel@tonic-gate #endif
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate #ifndef W_OK
90*0Sstevel@tonic-gate #  ifdef OPENSSL_SYS_VMS
91*0Sstevel@tonic-gate #    if defined(__DECC)
92*0Sstevel@tonic-gate #      include <unistd.h>
93*0Sstevel@tonic-gate #    else
94*0Sstevel@tonic-gate #      include <unixlib.h>
95*0Sstevel@tonic-gate #    endif
96*0Sstevel@tonic-gate #  elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
97*0Sstevel@tonic-gate #    include <sys/file.h>
98*0Sstevel@tonic-gate #  endif
99*0Sstevel@tonic-gate #endif
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate #include "apps.h"
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate #ifndef W_OK
104*0Sstevel@tonic-gate #  define F_OK 0
105*0Sstevel@tonic-gate #  define X_OK 1
106*0Sstevel@tonic-gate #  define W_OK 2
107*0Sstevel@tonic-gate #  define R_OK 4
108*0Sstevel@tonic-gate #endif
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate #undef PROG
111*0Sstevel@tonic-gate #define PROG ca_main
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate #define BASE_SECTION	"ca"
114*0Sstevel@tonic-gate #define CONFIG_FILE "openssl.cnf"
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate #define ENV_DEFAULT_CA		"default_ca"
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate #define ENV_DIR			"dir"
119*0Sstevel@tonic-gate #define ENV_CERTS		"certs"
120*0Sstevel@tonic-gate #define ENV_CRL_DIR		"crl_dir"
121*0Sstevel@tonic-gate #define ENV_CA_DB		"CA_DB"
122*0Sstevel@tonic-gate #define ENV_NEW_CERTS_DIR	"new_certs_dir"
123*0Sstevel@tonic-gate #define ENV_CERTIFICATE 	"certificate"
124*0Sstevel@tonic-gate #define ENV_SERIAL		"serial"
125*0Sstevel@tonic-gate #define ENV_CRLNUMBER		"crlnumber"
126*0Sstevel@tonic-gate #define ENV_CRL			"crl"
127*0Sstevel@tonic-gate #define ENV_PRIVATE_KEY		"private_key"
128*0Sstevel@tonic-gate #define ENV_RANDFILE		"RANDFILE"
129*0Sstevel@tonic-gate #define ENV_DEFAULT_DAYS 	"default_days"
130*0Sstevel@tonic-gate #define ENV_DEFAULT_STARTDATE 	"default_startdate"
131*0Sstevel@tonic-gate #define ENV_DEFAULT_ENDDATE 	"default_enddate"
132*0Sstevel@tonic-gate #define ENV_DEFAULT_CRL_DAYS 	"default_crl_days"
133*0Sstevel@tonic-gate #define ENV_DEFAULT_CRL_HOURS 	"default_crl_hours"
134*0Sstevel@tonic-gate #define ENV_DEFAULT_MD		"default_md"
135*0Sstevel@tonic-gate #define ENV_DEFAULT_EMAIL_DN	"email_in_dn"
136*0Sstevel@tonic-gate #define ENV_PRESERVE		"preserve"
137*0Sstevel@tonic-gate #define ENV_POLICY      	"policy"
138*0Sstevel@tonic-gate #define ENV_EXTENSIONS      	"x509_extensions"
139*0Sstevel@tonic-gate #define ENV_CRLEXT      	"crl_extensions"
140*0Sstevel@tonic-gate #define ENV_MSIE_HACK		"msie_hack"
141*0Sstevel@tonic-gate #define ENV_NAMEOPT		"name_opt"
142*0Sstevel@tonic-gate #define ENV_CERTOPT		"cert_opt"
143*0Sstevel@tonic-gate #define ENV_EXTCOPY		"copy_extensions"
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate #define ENV_DATABASE		"database"
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate /* Additional revocation information types */
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate #define REV_NONE		0	/* No addditional information */
150*0Sstevel@tonic-gate #define REV_CRL_REASON		1	/* Value is CRL reason code */
151*0Sstevel@tonic-gate #define REV_HOLD		2	/* Value is hold instruction */
152*0Sstevel@tonic-gate #define REV_KEY_COMPROMISE	3	/* Value is cert key compromise time */
153*0Sstevel@tonic-gate #define REV_CA_COMPROMISE	4	/* Value is CA key compromise time */
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate static char *ca_usage[]={
156*0Sstevel@tonic-gate "usage: ca args\n",
157*0Sstevel@tonic-gate "\n",
158*0Sstevel@tonic-gate " -verbose        - Talk alot while doing things\n",
159*0Sstevel@tonic-gate " -config file    - A config file\n",
160*0Sstevel@tonic-gate " -name arg       - The particular CA definition to use\n",
161*0Sstevel@tonic-gate " -gencrl         - Generate a new CRL\n",
162*0Sstevel@tonic-gate " -crldays days   - Days is when the next CRL is due\n",
163*0Sstevel@tonic-gate " -crlhours hours - Hours is when the next CRL is due\n",
164*0Sstevel@tonic-gate " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
165*0Sstevel@tonic-gate " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
166*0Sstevel@tonic-gate " -days arg       - number of days to certify the certificate for\n",
167*0Sstevel@tonic-gate " -md arg         - md to use, one of md2, md5, sha or sha1\n",
168*0Sstevel@tonic-gate " -policy arg     - The CA 'policy' to support\n",
169*0Sstevel@tonic-gate " -keyfile arg    - private key file\n",
170*0Sstevel@tonic-gate " -keyform arg    - private key file format (PEM or ENGINE)\n",
171*0Sstevel@tonic-gate " -key arg        - key to decode the private key if it is encrypted\n",
172*0Sstevel@tonic-gate " -cert file      - The CA certificate\n",
173*0Sstevel@tonic-gate " -in file        - The input PEM encoded certificate request(s)\n",
174*0Sstevel@tonic-gate " -out file       - Where to put the output file(s)\n",
175*0Sstevel@tonic-gate " -outdir dir     - Where to put output certificates\n",
176*0Sstevel@tonic-gate " -infiles ....   - The last argument, requests to process\n",
177*0Sstevel@tonic-gate " -spkac file     - File contains DN and signed public key and challenge\n",
178*0Sstevel@tonic-gate " -ss_cert file   - File contains a self signed cert to sign\n",
179*0Sstevel@tonic-gate " -preserveDN     - Don't re-order the DN\n",
180*0Sstevel@tonic-gate " -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
181*0Sstevel@tonic-gate " -batch          - Don't ask questions\n",
182*0Sstevel@tonic-gate " -msie_hack      - msie modifications to handle all those universal strings\n",
183*0Sstevel@tonic-gate " -revoke file    - Revoke a certificate (given in file)\n",
184*0Sstevel@tonic-gate " -subj arg       - Use arg instead of request's subject\n",
185*0Sstevel@tonic-gate " -extensions ..  - Extension section (override value in config file)\n",
186*0Sstevel@tonic-gate " -extfile file   - Configuration file with X509v3 extentions to add\n",
187*0Sstevel@tonic-gate " -crlexts ..     - CRL extension section (override value in config file)\n",
188*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
189*0Sstevel@tonic-gate " -engine e       - use engine e, possibly a hardware device.\n",
190*0Sstevel@tonic-gate #endif
191*0Sstevel@tonic-gate " -status serial  - Shows certificate status given the serial number\n",
192*0Sstevel@tonic-gate " -updatedb       - Updates db for expired certificates\n",
193*0Sstevel@tonic-gate NULL
194*0Sstevel@tonic-gate };
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate #ifdef EFENCE
197*0Sstevel@tonic-gate extern int EF_PROTECT_FREE;
198*0Sstevel@tonic-gate extern int EF_PROTECT_BELOW;
199*0Sstevel@tonic-gate extern int EF_ALIGNMENT;
200*0Sstevel@tonic-gate #endif
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate static void lookup_fail(char *name,char *tag);
203*0Sstevel@tonic-gate static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
204*0Sstevel@tonic-gate 		   const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
205*0Sstevel@tonic-gate 		   BIGNUM *serial, char *subj, int email_dn, char *startdate,
206*0Sstevel@tonic-gate 		   char *enddate, long days, int batch, char *ext_sect, CONF *conf,
207*0Sstevel@tonic-gate 		   int verbose, unsigned long certopt, unsigned long nameopt,
208*0Sstevel@tonic-gate 		   int default_op, int ext_copy);
209*0Sstevel@tonic-gate static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
210*0Sstevel@tonic-gate 			const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
211*0Sstevel@tonic-gate 			CA_DB *db, BIGNUM *serial, char *subj, int email_dn,
212*0Sstevel@tonic-gate 			char *startdate, char *enddate, long days, int batch,
213*0Sstevel@tonic-gate 			char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
214*0Sstevel@tonic-gate 			unsigned long nameopt, int default_op, int ext_copy,
215*0Sstevel@tonic-gate 			ENGINE *e);
216*0Sstevel@tonic-gate static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
217*0Sstevel@tonic-gate 			 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
218*0Sstevel@tonic-gate 			 CA_DB *db, BIGNUM *serial,char *subj, int email_dn,
219*0Sstevel@tonic-gate 			 char *startdate, char *enddate, long days, char *ext_sect,
220*0Sstevel@tonic-gate 			 CONF *conf, int verbose, unsigned long certopt,
221*0Sstevel@tonic-gate 			 unsigned long nameopt, int default_op, int ext_copy);
222*0Sstevel@tonic-gate static int fix_data(int nid, int *type);
223*0Sstevel@tonic-gate static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
224*0Sstevel@tonic-gate static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
225*0Sstevel@tonic-gate 	STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,
226*0Sstevel@tonic-gate 	int email_dn, char *startdate, char *enddate, long days, int batch,
227*0Sstevel@tonic-gate        	int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
228*0Sstevel@tonic-gate 	unsigned long certopt, unsigned long nameopt, int default_op,
229*0Sstevel@tonic-gate 	int ext_copy);
230*0Sstevel@tonic-gate static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
231*0Sstevel@tonic-gate static int get_certificate_status(const char *ser_status, CA_DB *db);
232*0Sstevel@tonic-gate static int do_updatedb(CA_DB *db);
233*0Sstevel@tonic-gate static int check_time_format(char *str);
234*0Sstevel@tonic-gate char *make_revocation_str(int rev_type, char *rev_arg);
235*0Sstevel@tonic-gate int make_revoked(X509_REVOKED *rev, char *str);
236*0Sstevel@tonic-gate int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
237*0Sstevel@tonic-gate static CONF *conf=NULL;
238*0Sstevel@tonic-gate static CONF *extconf=NULL;
239*0Sstevel@tonic-gate static char *section=NULL;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate static int preserve=0;
242*0Sstevel@tonic-gate static int msie_hack=0;
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate int MAIN(int, char **);
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate int MAIN(int argc, char **argv)
248*0Sstevel@tonic-gate 	{
249*0Sstevel@tonic-gate 	ENGINE *e = NULL;
250*0Sstevel@tonic-gate 	char *key=NULL,*passargin=NULL;
251*0Sstevel@tonic-gate 	int free_key = 0;
252*0Sstevel@tonic-gate 	int total=0;
253*0Sstevel@tonic-gate 	int total_done=0;
254*0Sstevel@tonic-gate 	int badops=0;
255*0Sstevel@tonic-gate 	int ret=1;
256*0Sstevel@tonic-gate 	int email_dn=1;
257*0Sstevel@tonic-gate 	int req=0;
258*0Sstevel@tonic-gate 	int verbose=0;
259*0Sstevel@tonic-gate 	int gencrl=0;
260*0Sstevel@tonic-gate 	int dorevoke=0;
261*0Sstevel@tonic-gate 	int doupdatedb=0;
262*0Sstevel@tonic-gate 	long crldays=0;
263*0Sstevel@tonic-gate 	long crlhours=0;
264*0Sstevel@tonic-gate 	long errorline= -1;
265*0Sstevel@tonic-gate 	char *configfile=NULL;
266*0Sstevel@tonic-gate 	char *md=NULL;
267*0Sstevel@tonic-gate 	char *policy=NULL;
268*0Sstevel@tonic-gate 	char *keyfile=NULL;
269*0Sstevel@tonic-gate 	char *certfile=NULL;
270*0Sstevel@tonic-gate 	int keyform=FORMAT_PEM;
271*0Sstevel@tonic-gate 	char *infile=NULL;
272*0Sstevel@tonic-gate 	char *spkac_file=NULL;
273*0Sstevel@tonic-gate 	char *ss_cert_file=NULL;
274*0Sstevel@tonic-gate 	char *ser_status=NULL;
275*0Sstevel@tonic-gate 	EVP_PKEY *pkey=NULL;
276*0Sstevel@tonic-gate 	int output_der = 0;
277*0Sstevel@tonic-gate 	char *outfile=NULL;
278*0Sstevel@tonic-gate 	char *outdir=NULL;
279*0Sstevel@tonic-gate 	char *serialfile=NULL;
280*0Sstevel@tonic-gate 	char *crlnumberfile=NULL;
281*0Sstevel@tonic-gate 	char *extensions=NULL;
282*0Sstevel@tonic-gate 	char *extfile=NULL;
283*0Sstevel@tonic-gate 	char *subj=NULL;
284*0Sstevel@tonic-gate 	char *tmp_email_dn=NULL;
285*0Sstevel@tonic-gate 	char *crl_ext=NULL;
286*0Sstevel@tonic-gate 	int rev_type = REV_NONE;
287*0Sstevel@tonic-gate 	char *rev_arg = NULL;
288*0Sstevel@tonic-gate 	BIGNUM *serial=NULL;
289*0Sstevel@tonic-gate 	BIGNUM *crlnumber=NULL;
290*0Sstevel@tonic-gate 	char *startdate=NULL;
291*0Sstevel@tonic-gate 	char *enddate=NULL;
292*0Sstevel@tonic-gate 	long days=0;
293*0Sstevel@tonic-gate 	int batch=0;
294*0Sstevel@tonic-gate 	int notext=0;
295*0Sstevel@tonic-gate 	unsigned long nameopt = 0, certopt = 0;
296*0Sstevel@tonic-gate 	int default_op = 1;
297*0Sstevel@tonic-gate 	int ext_copy = EXT_COPY_NONE;
298*0Sstevel@tonic-gate 	X509 *x509=NULL;
299*0Sstevel@tonic-gate 	X509 *x=NULL;
300*0Sstevel@tonic-gate 	BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
301*0Sstevel@tonic-gate 	char *dbfile=NULL;
302*0Sstevel@tonic-gate 	CA_DB *db=NULL;
303*0Sstevel@tonic-gate 	X509_CRL *crl=NULL;
304*0Sstevel@tonic-gate 	X509_REVOKED *r=NULL;
305*0Sstevel@tonic-gate 	ASN1_TIME *tmptm;
306*0Sstevel@tonic-gate 	ASN1_INTEGER *tmpser;
307*0Sstevel@tonic-gate 	char **pp,*p,*f;
308*0Sstevel@tonic-gate 	int i,j;
309*0Sstevel@tonic-gate 	const EVP_MD *dgst=NULL;
310*0Sstevel@tonic-gate 	STACK_OF(CONF_VALUE) *attribs=NULL;
311*0Sstevel@tonic-gate 	STACK_OF(X509) *cert_sk=NULL;
312*0Sstevel@tonic-gate #undef BSIZE
313*0Sstevel@tonic-gate #define BSIZE 256
314*0Sstevel@tonic-gate 	MS_STATIC char buf[3][BSIZE];
315*0Sstevel@tonic-gate 	char *randfile=NULL;
316*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
317*0Sstevel@tonic-gate 	char *engine = NULL;
318*0Sstevel@tonic-gate #endif
319*0Sstevel@tonic-gate 	char *tofree=NULL;
320*0Sstevel@tonic-gate 	DB_ATTR db_attr;
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate #ifdef EFENCE
323*0Sstevel@tonic-gate EF_PROTECT_FREE=1;
324*0Sstevel@tonic-gate EF_PROTECT_BELOW=1;
325*0Sstevel@tonic-gate EF_ALIGNMENT=0;
326*0Sstevel@tonic-gate #endif
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 	apps_startup();
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	conf = NULL;
331*0Sstevel@tonic-gate 	key = NULL;
332*0Sstevel@tonic-gate 	section = NULL;
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	preserve=0;
335*0Sstevel@tonic-gate 	msie_hack=0;
336*0Sstevel@tonic-gate 	if (bio_err == NULL)
337*0Sstevel@tonic-gate 		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
338*0Sstevel@tonic-gate 			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 	argc--;
341*0Sstevel@tonic-gate 	argv++;
342*0Sstevel@tonic-gate 	while (argc >= 1)
343*0Sstevel@tonic-gate 		{
344*0Sstevel@tonic-gate 		if	(strcmp(*argv,"-verbose") == 0)
345*0Sstevel@tonic-gate 			verbose=1;
346*0Sstevel@tonic-gate 		else if	(strcmp(*argv,"-config") == 0)
347*0Sstevel@tonic-gate 			{
348*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
349*0Sstevel@tonic-gate 			configfile= *(++argv);
350*0Sstevel@tonic-gate 			}
351*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-name") == 0)
352*0Sstevel@tonic-gate 			{
353*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
354*0Sstevel@tonic-gate 			section= *(++argv);
355*0Sstevel@tonic-gate 			}
356*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-subj") == 0)
357*0Sstevel@tonic-gate 			{
358*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
359*0Sstevel@tonic-gate 			subj= *(++argv);
360*0Sstevel@tonic-gate 			/* preserve=1; */
361*0Sstevel@tonic-gate 			}
362*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-startdate") == 0)
363*0Sstevel@tonic-gate 			{
364*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
365*0Sstevel@tonic-gate 			startdate= *(++argv);
366*0Sstevel@tonic-gate 			}
367*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-enddate") == 0)
368*0Sstevel@tonic-gate 			{
369*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
370*0Sstevel@tonic-gate 			enddate= *(++argv);
371*0Sstevel@tonic-gate 			}
372*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-days") == 0)
373*0Sstevel@tonic-gate 			{
374*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
375*0Sstevel@tonic-gate 			days=atoi(*(++argv));
376*0Sstevel@tonic-gate 			}
377*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-md") == 0)
378*0Sstevel@tonic-gate 			{
379*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
380*0Sstevel@tonic-gate 			md= *(++argv);
381*0Sstevel@tonic-gate 			}
382*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-policy") == 0)
383*0Sstevel@tonic-gate 			{
384*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
385*0Sstevel@tonic-gate 			policy= *(++argv);
386*0Sstevel@tonic-gate 			}
387*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-keyfile") == 0)
388*0Sstevel@tonic-gate 			{
389*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
390*0Sstevel@tonic-gate 			keyfile= *(++argv);
391*0Sstevel@tonic-gate 			}
392*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-keyform") == 0)
393*0Sstevel@tonic-gate 			{
394*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
395*0Sstevel@tonic-gate 			keyform=str2fmt(*(++argv));
396*0Sstevel@tonic-gate 			}
397*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-passin") == 0)
398*0Sstevel@tonic-gate 			{
399*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
400*0Sstevel@tonic-gate 			passargin= *(++argv);
401*0Sstevel@tonic-gate 			}
402*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-key") == 0)
403*0Sstevel@tonic-gate 			{
404*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
405*0Sstevel@tonic-gate 			key= *(++argv);
406*0Sstevel@tonic-gate 			}
407*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-cert") == 0)
408*0Sstevel@tonic-gate 			{
409*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
410*0Sstevel@tonic-gate 			certfile= *(++argv);
411*0Sstevel@tonic-gate 			}
412*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-in") == 0)
413*0Sstevel@tonic-gate 			{
414*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
415*0Sstevel@tonic-gate 			infile= *(++argv);
416*0Sstevel@tonic-gate 			req=1;
417*0Sstevel@tonic-gate 			}
418*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-out") == 0)
419*0Sstevel@tonic-gate 			{
420*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
421*0Sstevel@tonic-gate 			outfile= *(++argv);
422*0Sstevel@tonic-gate 			}
423*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-outdir") == 0)
424*0Sstevel@tonic-gate 			{
425*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
426*0Sstevel@tonic-gate 			outdir= *(++argv);
427*0Sstevel@tonic-gate 			}
428*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-notext") == 0)
429*0Sstevel@tonic-gate 			notext=1;
430*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-batch") == 0)
431*0Sstevel@tonic-gate 			batch=1;
432*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-preserveDN") == 0)
433*0Sstevel@tonic-gate 			preserve=1;
434*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-noemailDN") == 0)
435*0Sstevel@tonic-gate 			email_dn=0;
436*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-gencrl") == 0)
437*0Sstevel@tonic-gate 			gencrl=1;
438*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-msie_hack") == 0)
439*0Sstevel@tonic-gate 			msie_hack=1;
440*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crldays") == 0)
441*0Sstevel@tonic-gate 			{
442*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
443*0Sstevel@tonic-gate 			crldays= atol(*(++argv));
444*0Sstevel@tonic-gate 			}
445*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crlhours") == 0)
446*0Sstevel@tonic-gate 			{
447*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
448*0Sstevel@tonic-gate 			crlhours= atol(*(++argv));
449*0Sstevel@tonic-gate 			}
450*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-infiles") == 0)
451*0Sstevel@tonic-gate 			{
452*0Sstevel@tonic-gate 			argc--;
453*0Sstevel@tonic-gate 			argv++;
454*0Sstevel@tonic-gate 			req=1;
455*0Sstevel@tonic-gate 			break;
456*0Sstevel@tonic-gate 			}
457*0Sstevel@tonic-gate 		else if (strcmp(*argv, "-ss_cert") == 0)
458*0Sstevel@tonic-gate 			{
459*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
460*0Sstevel@tonic-gate 			ss_cert_file = *(++argv);
461*0Sstevel@tonic-gate 			req=1;
462*0Sstevel@tonic-gate 			}
463*0Sstevel@tonic-gate 		else if (strcmp(*argv, "-spkac") == 0)
464*0Sstevel@tonic-gate 			{
465*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
466*0Sstevel@tonic-gate 			spkac_file = *(++argv);
467*0Sstevel@tonic-gate 			req=1;
468*0Sstevel@tonic-gate 			}
469*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-revoke") == 0)
470*0Sstevel@tonic-gate 			{
471*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
472*0Sstevel@tonic-gate 			infile= *(++argv);
473*0Sstevel@tonic-gate 			dorevoke=1;
474*0Sstevel@tonic-gate 			}
475*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-extensions") == 0)
476*0Sstevel@tonic-gate 			{
477*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
478*0Sstevel@tonic-gate 			extensions= *(++argv);
479*0Sstevel@tonic-gate 			}
480*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-extfile") == 0)
481*0Sstevel@tonic-gate 			{
482*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
483*0Sstevel@tonic-gate 			extfile= *(++argv);
484*0Sstevel@tonic-gate 			}
485*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-status") == 0)
486*0Sstevel@tonic-gate 			{
487*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
488*0Sstevel@tonic-gate 			ser_status= *(++argv);
489*0Sstevel@tonic-gate 			}
490*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-updatedb") == 0)
491*0Sstevel@tonic-gate 			{
492*0Sstevel@tonic-gate 			doupdatedb=1;
493*0Sstevel@tonic-gate 			}
494*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crlexts") == 0)
495*0Sstevel@tonic-gate 			{
496*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
497*0Sstevel@tonic-gate 			crl_ext= *(++argv);
498*0Sstevel@tonic-gate 			}
499*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crl_reason") == 0)
500*0Sstevel@tonic-gate 			{
501*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
502*0Sstevel@tonic-gate 			rev_arg = *(++argv);
503*0Sstevel@tonic-gate 			rev_type = REV_CRL_REASON;
504*0Sstevel@tonic-gate 			}
505*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crl_hold") == 0)
506*0Sstevel@tonic-gate 			{
507*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
508*0Sstevel@tonic-gate 			rev_arg = *(++argv);
509*0Sstevel@tonic-gate 			rev_type = REV_HOLD;
510*0Sstevel@tonic-gate 			}
511*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crl_compromise") == 0)
512*0Sstevel@tonic-gate 			{
513*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
514*0Sstevel@tonic-gate 			rev_arg = *(++argv);
515*0Sstevel@tonic-gate 			rev_type = REV_KEY_COMPROMISE;
516*0Sstevel@tonic-gate 			}
517*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-crl_CA_compromise") == 0)
518*0Sstevel@tonic-gate 			{
519*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
520*0Sstevel@tonic-gate 			rev_arg = *(++argv);
521*0Sstevel@tonic-gate 			rev_type = REV_CA_COMPROMISE;
522*0Sstevel@tonic-gate 			}
523*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
524*0Sstevel@tonic-gate 		else if (strcmp(*argv,"-engine") == 0)
525*0Sstevel@tonic-gate 			{
526*0Sstevel@tonic-gate 			if (--argc < 1) goto bad;
527*0Sstevel@tonic-gate 			engine= *(++argv);
528*0Sstevel@tonic-gate 			}
529*0Sstevel@tonic-gate #endif
530*0Sstevel@tonic-gate 		else
531*0Sstevel@tonic-gate 			{
532*0Sstevel@tonic-gate bad:
533*0Sstevel@tonic-gate 			BIO_printf(bio_err,"unknown option %s\n",*argv);
534*0Sstevel@tonic-gate 			badops=1;
535*0Sstevel@tonic-gate 			break;
536*0Sstevel@tonic-gate 			}
537*0Sstevel@tonic-gate 		argc--;
538*0Sstevel@tonic-gate 		argv++;
539*0Sstevel@tonic-gate 		}
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	if (badops)
542*0Sstevel@tonic-gate 		{
543*0Sstevel@tonic-gate 		for (pp=ca_usage; (*pp != NULL); pp++)
544*0Sstevel@tonic-gate 			BIO_printf(bio_err,"%s",*pp);
545*0Sstevel@tonic-gate 		goto err;
546*0Sstevel@tonic-gate 		}
547*0Sstevel@tonic-gate 
548*0Sstevel@tonic-gate 	ERR_load_crypto_strings();
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
551*0Sstevel@tonic-gate 	e = setup_engine(bio_err, engine, 0);
552*0Sstevel@tonic-gate #endif
553*0Sstevel@tonic-gate 
554*0Sstevel@tonic-gate 	/*****************************************************************/
555*0Sstevel@tonic-gate 	tofree=NULL;
556*0Sstevel@tonic-gate 	if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
557*0Sstevel@tonic-gate 	if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
558*0Sstevel@tonic-gate 	if (configfile == NULL)
559*0Sstevel@tonic-gate 		{
560*0Sstevel@tonic-gate 		const char *s=X509_get_default_cert_area();
561*0Sstevel@tonic-gate 		size_t len;
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
564*0Sstevel@tonic-gate 		len = strlen(s)+sizeof(CONFIG_FILE);
565*0Sstevel@tonic-gate 		tofree=OPENSSL_malloc(len);
566*0Sstevel@tonic-gate 		strcpy(tofree,s);
567*0Sstevel@tonic-gate #else
568*0Sstevel@tonic-gate 		len = strlen(s)+sizeof(CONFIG_FILE)+1;
569*0Sstevel@tonic-gate 		tofree=OPENSSL_malloc(len);
570*0Sstevel@tonic-gate 		BUF_strlcpy(tofree,s,len);
571*0Sstevel@tonic-gate 		BUF_strlcat(tofree,"/",len);
572*0Sstevel@tonic-gate #endif
573*0Sstevel@tonic-gate 		BUF_strlcat(tofree,CONFIG_FILE,len);
574*0Sstevel@tonic-gate 		configfile=tofree;
575*0Sstevel@tonic-gate 		}
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Using configuration from %s\n",configfile);
578*0Sstevel@tonic-gate 	conf = NCONF_new(NULL);
579*0Sstevel@tonic-gate 	if (NCONF_load(conf,configfile,&errorline) <= 0)
580*0Sstevel@tonic-gate 		{
581*0Sstevel@tonic-gate 		if (errorline <= 0)
582*0Sstevel@tonic-gate 			BIO_printf(bio_err,"error loading the config file '%s'\n",
583*0Sstevel@tonic-gate 				configfile);
584*0Sstevel@tonic-gate 		else
585*0Sstevel@tonic-gate 			BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
586*0Sstevel@tonic-gate 				,errorline,configfile);
587*0Sstevel@tonic-gate 		goto err;
588*0Sstevel@tonic-gate 		}
589*0Sstevel@tonic-gate 	if(tofree)
590*0Sstevel@tonic-gate 		{
591*0Sstevel@tonic-gate 		OPENSSL_free(tofree);
592*0Sstevel@tonic-gate 		tofree = NULL;
593*0Sstevel@tonic-gate 		}
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 	if (!load_config(bio_err, conf))
596*0Sstevel@tonic-gate 		goto err;
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 	/* Lets get the config section we are using */
599*0Sstevel@tonic-gate 	if (section == NULL)
600*0Sstevel@tonic-gate 		{
601*0Sstevel@tonic-gate 		section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
602*0Sstevel@tonic-gate 		if (section == NULL)
603*0Sstevel@tonic-gate 			{
604*0Sstevel@tonic-gate 			lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
605*0Sstevel@tonic-gate 			goto err;
606*0Sstevel@tonic-gate 			}
607*0Sstevel@tonic-gate 		}
608*0Sstevel@tonic-gate 
609*0Sstevel@tonic-gate 	if (conf != NULL)
610*0Sstevel@tonic-gate 		{
611*0Sstevel@tonic-gate 		p=NCONF_get_string(conf,NULL,"oid_file");
612*0Sstevel@tonic-gate 		if (p == NULL)
613*0Sstevel@tonic-gate 			ERR_clear_error();
614*0Sstevel@tonic-gate 		if (p != NULL)
615*0Sstevel@tonic-gate 			{
616*0Sstevel@tonic-gate 			BIO *oid_bio;
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 			oid_bio=BIO_new_file(p,"r");
619*0Sstevel@tonic-gate 			if (oid_bio == NULL)
620*0Sstevel@tonic-gate 				{
621*0Sstevel@tonic-gate 				/*
622*0Sstevel@tonic-gate 				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
623*0Sstevel@tonic-gate 				ERR_print_errors(bio_err);
624*0Sstevel@tonic-gate 				*/
625*0Sstevel@tonic-gate 				ERR_clear_error();
626*0Sstevel@tonic-gate 				}
627*0Sstevel@tonic-gate 			else
628*0Sstevel@tonic-gate 				{
629*0Sstevel@tonic-gate 				OBJ_create_objects(oid_bio);
630*0Sstevel@tonic-gate 				BIO_free(oid_bio);
631*0Sstevel@tonic-gate 				}
632*0Sstevel@tonic-gate 			}
633*0Sstevel@tonic-gate 		if (!add_oid_section(bio_err,conf))
634*0Sstevel@tonic-gate 			{
635*0Sstevel@tonic-gate 			ERR_print_errors(bio_err);
636*0Sstevel@tonic-gate 			goto err;
637*0Sstevel@tonic-gate 			}
638*0Sstevel@tonic-gate 		}
639*0Sstevel@tonic-gate 
640*0Sstevel@tonic-gate 	randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
641*0Sstevel@tonic-gate 	if (randfile == NULL)
642*0Sstevel@tonic-gate 		ERR_clear_error();
643*0Sstevel@tonic-gate 	app_RAND_load_file(randfile, bio_err, 0);
644*0Sstevel@tonic-gate 
645*0Sstevel@tonic-gate 	db_attr.unique_subject = 1;
646*0Sstevel@tonic-gate 	p = NCONF_get_string(conf, section, "unique_subject");
647*0Sstevel@tonic-gate 	if (p)
648*0Sstevel@tonic-gate 		{
649*0Sstevel@tonic-gate #ifdef RL_DEBUG
650*0Sstevel@tonic-gate 		BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
651*0Sstevel@tonic-gate #endif
652*0Sstevel@tonic-gate 		switch(*p)
653*0Sstevel@tonic-gate 			{
654*0Sstevel@tonic-gate 		case 'f': /* false */
655*0Sstevel@tonic-gate 		case 'F': /* FALSE */
656*0Sstevel@tonic-gate 		case 'n': /* no */
657*0Sstevel@tonic-gate 		case 'N': /* NO */
658*0Sstevel@tonic-gate 			db_attr.unique_subject = 0;
659*0Sstevel@tonic-gate 			break;
660*0Sstevel@tonic-gate 		case 't': /* true */
661*0Sstevel@tonic-gate 		case 'T': /* TRUE */
662*0Sstevel@tonic-gate 		case 'y': /* yes */
663*0Sstevel@tonic-gate 		case 'Y': /* YES */
664*0Sstevel@tonic-gate 		default:
665*0Sstevel@tonic-gate 			db_attr.unique_subject = 1;
666*0Sstevel@tonic-gate 			break;
667*0Sstevel@tonic-gate 			}
668*0Sstevel@tonic-gate 		}
669*0Sstevel@tonic-gate #ifdef RL_DEBUG
670*0Sstevel@tonic-gate 	else
671*0Sstevel@tonic-gate 		BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
672*0Sstevel@tonic-gate #endif
673*0Sstevel@tonic-gate #ifdef RL_DEBUG
674*0Sstevel@tonic-gate 	BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
675*0Sstevel@tonic-gate 		db_attr.unique_subject);
676*0Sstevel@tonic-gate #endif
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate 	in=BIO_new(BIO_s_file());
679*0Sstevel@tonic-gate 	out=BIO_new(BIO_s_file());
680*0Sstevel@tonic-gate 	Sout=BIO_new(BIO_s_file());
681*0Sstevel@tonic-gate 	Cout=BIO_new(BIO_s_file());
682*0Sstevel@tonic-gate 	if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
683*0Sstevel@tonic-gate 		{
684*0Sstevel@tonic-gate 		ERR_print_errors(bio_err);
685*0Sstevel@tonic-gate 		goto err;
686*0Sstevel@tonic-gate 		}
687*0Sstevel@tonic-gate 
688*0Sstevel@tonic-gate 	/*****************************************************************/
689*0Sstevel@tonic-gate 	/* report status of cert with serial number given on command line */
690*0Sstevel@tonic-gate 	if (ser_status)
691*0Sstevel@tonic-gate 	{
692*0Sstevel@tonic-gate 		if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
693*0Sstevel@tonic-gate 			{
694*0Sstevel@tonic-gate 			lookup_fail(section,ENV_DATABASE);
695*0Sstevel@tonic-gate 			goto err;
696*0Sstevel@tonic-gate 			}
697*0Sstevel@tonic-gate 		db = load_index(dbfile,&db_attr);
698*0Sstevel@tonic-gate 		if (db == NULL) goto err;
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate 		if (!index_index(db)) goto err;
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate 		if (get_certificate_status(ser_status,db) != 1)
703*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Error verifying serial %s!\n",
704*0Sstevel@tonic-gate 				 ser_status);
705*0Sstevel@tonic-gate 		goto err;
706*0Sstevel@tonic-gate 	}
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	/*****************************************************************/
709*0Sstevel@tonic-gate 	/* we definitely need a public key, so let's get it */
710*0Sstevel@tonic-gate 
711*0Sstevel@tonic-gate 	if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
712*0Sstevel@tonic-gate 		section,ENV_PRIVATE_KEY)) == NULL))
713*0Sstevel@tonic-gate 		{
714*0Sstevel@tonic-gate 		lookup_fail(section,ENV_PRIVATE_KEY);
715*0Sstevel@tonic-gate 		goto err;
716*0Sstevel@tonic-gate 		}
717*0Sstevel@tonic-gate 	if (!key)
718*0Sstevel@tonic-gate 		{
719*0Sstevel@tonic-gate 		free_key = 1;
720*0Sstevel@tonic-gate 		if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
721*0Sstevel@tonic-gate 			{
722*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Error getting password\n");
723*0Sstevel@tonic-gate 			goto err;
724*0Sstevel@tonic-gate 			}
725*0Sstevel@tonic-gate 		}
726*0Sstevel@tonic-gate 	pkey = load_key(bio_err, keyfile, keyform, 0, key, e,
727*0Sstevel@tonic-gate 		"CA private key");
728*0Sstevel@tonic-gate 	if (key) OPENSSL_cleanse(key,strlen(key));
729*0Sstevel@tonic-gate 	if (pkey == NULL)
730*0Sstevel@tonic-gate 		{
731*0Sstevel@tonic-gate 		/* load_key() has already printed an appropriate message */
732*0Sstevel@tonic-gate 		goto err;
733*0Sstevel@tonic-gate 		}
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 	/*****************************************************************/
736*0Sstevel@tonic-gate 	/* we need a certificate */
737*0Sstevel@tonic-gate 	if ((certfile == NULL) && ((certfile=NCONF_get_string(conf,
738*0Sstevel@tonic-gate 		section,ENV_CERTIFICATE)) == NULL))
739*0Sstevel@tonic-gate 		{
740*0Sstevel@tonic-gate 		lookup_fail(section,ENV_CERTIFICATE);
741*0Sstevel@tonic-gate 		goto err;
742*0Sstevel@tonic-gate 		}
743*0Sstevel@tonic-gate 	x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
744*0Sstevel@tonic-gate 		"CA certificate");
745*0Sstevel@tonic-gate 	if (x509 == NULL)
746*0Sstevel@tonic-gate 		goto err;
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	if (!X509_check_private_key(x509,pkey))
749*0Sstevel@tonic-gate 		{
750*0Sstevel@tonic-gate 		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
751*0Sstevel@tonic-gate 		goto err;
752*0Sstevel@tonic-gate 		}
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate 	f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
755*0Sstevel@tonic-gate 	if (f == NULL)
756*0Sstevel@tonic-gate 		ERR_clear_error();
757*0Sstevel@tonic-gate 	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
758*0Sstevel@tonic-gate 		preserve=1;
759*0Sstevel@tonic-gate 	f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
760*0Sstevel@tonic-gate 	if (f == NULL)
761*0Sstevel@tonic-gate 		ERR_clear_error();
762*0Sstevel@tonic-gate 	if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
763*0Sstevel@tonic-gate 		msie_hack=1;
764*0Sstevel@tonic-gate 
765*0Sstevel@tonic-gate 	f=NCONF_get_string(conf,section,ENV_NAMEOPT);
766*0Sstevel@tonic-gate 
767*0Sstevel@tonic-gate 	if (f)
768*0Sstevel@tonic-gate 		{
769*0Sstevel@tonic-gate 		if (!set_name_ex(&nameopt, f))
770*0Sstevel@tonic-gate 			{
771*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
772*0Sstevel@tonic-gate 			goto err;
773*0Sstevel@tonic-gate 			}
774*0Sstevel@tonic-gate 		default_op = 0;
775*0Sstevel@tonic-gate 		}
776*0Sstevel@tonic-gate 	else
777*0Sstevel@tonic-gate 		ERR_clear_error();
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate 	f=NCONF_get_string(conf,section,ENV_CERTOPT);
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate 	if (f)
782*0Sstevel@tonic-gate 		{
783*0Sstevel@tonic-gate 		if (!set_cert_ex(&certopt, f))
784*0Sstevel@tonic-gate 			{
785*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
786*0Sstevel@tonic-gate 			goto err;
787*0Sstevel@tonic-gate 			}
788*0Sstevel@tonic-gate 		default_op = 0;
789*0Sstevel@tonic-gate 		}
790*0Sstevel@tonic-gate 	else
791*0Sstevel@tonic-gate 		ERR_clear_error();
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate 	f=NCONF_get_string(conf,section,ENV_EXTCOPY);
794*0Sstevel@tonic-gate 
795*0Sstevel@tonic-gate 	if (f)
796*0Sstevel@tonic-gate 		{
797*0Sstevel@tonic-gate 		if (!set_ext_copy(&ext_copy, f))
798*0Sstevel@tonic-gate 			{
799*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
800*0Sstevel@tonic-gate 			goto err;
801*0Sstevel@tonic-gate 			}
802*0Sstevel@tonic-gate 		}
803*0Sstevel@tonic-gate 	else
804*0Sstevel@tonic-gate 		ERR_clear_error();
805*0Sstevel@tonic-gate 
806*0Sstevel@tonic-gate 	/*****************************************************************/
807*0Sstevel@tonic-gate 	/* lookup where to write new certificates */
808*0Sstevel@tonic-gate 	if ((outdir == NULL) && (req))
809*0Sstevel@tonic-gate 		{
810*0Sstevel@tonic-gate 		struct stat sb;
811*0Sstevel@tonic-gate 
812*0Sstevel@tonic-gate 		if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
813*0Sstevel@tonic-gate 			== NULL)
814*0Sstevel@tonic-gate 			{
815*0Sstevel@tonic-gate 			BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
816*0Sstevel@tonic-gate 			goto err;
817*0Sstevel@tonic-gate 			}
818*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_VMS
819*0Sstevel@tonic-gate 	    /* outdir is a directory spec, but access() for VMS demands a
820*0Sstevel@tonic-gate 	       filename.  In any case, stat(), below, will catch the problem
821*0Sstevel@tonic-gate 	       if outdir is not a directory spec, and the fopen() or open()
822*0Sstevel@tonic-gate 	       will catch an error if there is no write access.
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate 	       Presumably, this problem could also be solved by using the DEC
825*0Sstevel@tonic-gate 	       C routines to convert the directory syntax to Unixly, and give
826*0Sstevel@tonic-gate 	       that to access().  However, time's too short to do that just
827*0Sstevel@tonic-gate 	       now.
828*0Sstevel@tonic-gate 	    */
829*0Sstevel@tonic-gate 		if (access(outdir,R_OK|W_OK|X_OK) != 0)
830*0Sstevel@tonic-gate 			{
831*0Sstevel@tonic-gate 			BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
832*0Sstevel@tonic-gate 			perror(outdir);
833*0Sstevel@tonic-gate 			goto err;
834*0Sstevel@tonic-gate 			}
835*0Sstevel@tonic-gate 
836*0Sstevel@tonic-gate 		if (stat(outdir,&sb) != 0)
837*0Sstevel@tonic-gate 			{
838*0Sstevel@tonic-gate 			BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
839*0Sstevel@tonic-gate 			perror(outdir);
840*0Sstevel@tonic-gate 			goto err;
841*0Sstevel@tonic-gate 			}
842*0Sstevel@tonic-gate #ifdef S_IFDIR
843*0Sstevel@tonic-gate 		if (!(sb.st_mode & S_IFDIR))
844*0Sstevel@tonic-gate 			{
845*0Sstevel@tonic-gate 			BIO_printf(bio_err,"%s need to be a directory\n",outdir);
846*0Sstevel@tonic-gate 			perror(outdir);
847*0Sstevel@tonic-gate 			goto err;
848*0Sstevel@tonic-gate 			}
849*0Sstevel@tonic-gate #endif
850*0Sstevel@tonic-gate #endif
851*0Sstevel@tonic-gate 		}
852*0Sstevel@tonic-gate 
853*0Sstevel@tonic-gate 	/*****************************************************************/
854*0Sstevel@tonic-gate 	/* we need to load the database file */
855*0Sstevel@tonic-gate 	if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
856*0Sstevel@tonic-gate 		{
857*0Sstevel@tonic-gate 		lookup_fail(section,ENV_DATABASE);
858*0Sstevel@tonic-gate 		goto err;
859*0Sstevel@tonic-gate 		}
860*0Sstevel@tonic-gate 	db = load_index(dbfile, &db_attr);
861*0Sstevel@tonic-gate 	if (db == NULL) goto err;
862*0Sstevel@tonic-gate 
863*0Sstevel@tonic-gate 	/* Lets check some fields */
864*0Sstevel@tonic-gate 	for (i=0; i<sk_num(db->db->data); i++)
865*0Sstevel@tonic-gate 		{
866*0Sstevel@tonic-gate 		pp=(char **)sk_value(db->db->data,i);
867*0Sstevel@tonic-gate 		if ((pp[DB_type][0] != DB_TYPE_REV) &&
868*0Sstevel@tonic-gate 			(pp[DB_rev_date][0] != '\0'))
869*0Sstevel@tonic-gate 			{
870*0Sstevel@tonic-gate 			BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
871*0Sstevel@tonic-gate 			goto err;
872*0Sstevel@tonic-gate 			}
873*0Sstevel@tonic-gate 		if ((pp[DB_type][0] == DB_TYPE_REV) &&
874*0Sstevel@tonic-gate 			!make_revoked(NULL, pp[DB_rev_date]))
875*0Sstevel@tonic-gate 			{
876*0Sstevel@tonic-gate 			BIO_printf(bio_err," in entry %d\n", i+1);
877*0Sstevel@tonic-gate 			goto err;
878*0Sstevel@tonic-gate 			}
879*0Sstevel@tonic-gate 		if (!check_time_format(pp[DB_exp_date]))
880*0Sstevel@tonic-gate 			{
881*0Sstevel@tonic-gate 			BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
882*0Sstevel@tonic-gate 			goto err;
883*0Sstevel@tonic-gate 			}
884*0Sstevel@tonic-gate 		p=pp[DB_serial];
885*0Sstevel@tonic-gate 		j=strlen(p);
886*0Sstevel@tonic-gate 		if (*p == '-')
887*0Sstevel@tonic-gate 			{
888*0Sstevel@tonic-gate 			p++;
889*0Sstevel@tonic-gate 			j--;
890*0Sstevel@tonic-gate 			}
891*0Sstevel@tonic-gate 		if ((j&1) || (j < 2))
892*0Sstevel@tonic-gate 			{
893*0Sstevel@tonic-gate 			BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
894*0Sstevel@tonic-gate 			goto err;
895*0Sstevel@tonic-gate 			}
896*0Sstevel@tonic-gate 		while (*p)
897*0Sstevel@tonic-gate 			{
898*0Sstevel@tonic-gate 			if (!(	((*p >= '0') && (*p <= '9')) ||
899*0Sstevel@tonic-gate 				((*p >= 'A') && (*p <= 'F')) ||
900*0Sstevel@tonic-gate 				((*p >= 'a') && (*p <= 'f')))  )
901*0Sstevel@tonic-gate 				{
902*0Sstevel@tonic-gate 				BIO_printf(bio_err,"entry %d: bad serial number characters, char pos %ld, char is '%c'\n",i+1,(long)(p-pp[DB_serial]),*p);
903*0Sstevel@tonic-gate 				goto err;
904*0Sstevel@tonic-gate 				}
905*0Sstevel@tonic-gate 			p++;
906*0Sstevel@tonic-gate 			}
907*0Sstevel@tonic-gate 		}
908*0Sstevel@tonic-gate 	if (verbose)
909*0Sstevel@tonic-gate 		{
910*0Sstevel@tonic-gate 		BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
911*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
912*0Sstevel@tonic-gate 		{
913*0Sstevel@tonic-gate 		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
914*0Sstevel@tonic-gate 		out = BIO_push(tmpbio, out);
915*0Sstevel@tonic-gate 		}
916*0Sstevel@tonic-gate #endif
917*0Sstevel@tonic-gate 		TXT_DB_write(out,db->db);
918*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%d entries loaded from the database\n",
919*0Sstevel@tonic-gate 			db->db->data->num);
920*0Sstevel@tonic-gate 		BIO_printf(bio_err,"generating index\n");
921*0Sstevel@tonic-gate 		}
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate 	if (!index_index(db)) goto err;
924*0Sstevel@tonic-gate 
925*0Sstevel@tonic-gate 	/*****************************************************************/
926*0Sstevel@tonic-gate 	/* Update the db file for expired certificates */
927*0Sstevel@tonic-gate 	if (doupdatedb)
928*0Sstevel@tonic-gate 		{
929*0Sstevel@tonic-gate 		if (verbose)
930*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Updating %s ...\n",
931*0Sstevel@tonic-gate 							dbfile);
932*0Sstevel@tonic-gate 
933*0Sstevel@tonic-gate 		i = do_updatedb(db);
934*0Sstevel@tonic-gate 		if (i == -1)
935*0Sstevel@tonic-gate 			{
936*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Malloc failure\n");
937*0Sstevel@tonic-gate 			goto err;
938*0Sstevel@tonic-gate 			}
939*0Sstevel@tonic-gate 		else if (i == 0)
940*0Sstevel@tonic-gate 			{
941*0Sstevel@tonic-gate 			if (verbose) BIO_printf(bio_err,
942*0Sstevel@tonic-gate 					"No entries found to mark expired\n");
943*0Sstevel@tonic-gate 			}
944*0Sstevel@tonic-gate 	    	else
945*0Sstevel@tonic-gate 			{
946*0Sstevel@tonic-gate 			if (!save_index(dbfile,"new",db)) goto err;
947*0Sstevel@tonic-gate 
948*0Sstevel@tonic-gate 			if (!rotate_index(dbfile,"new","old")) goto err;
949*0Sstevel@tonic-gate 
950*0Sstevel@tonic-gate 			if (verbose) BIO_printf(bio_err,
951*0Sstevel@tonic-gate 				"Done. %d entries marked as expired\n",i);
952*0Sstevel@tonic-gate 	      		}
953*0Sstevel@tonic-gate 			goto err;
954*0Sstevel@tonic-gate 	  	}
955*0Sstevel@tonic-gate 
956*0Sstevel@tonic-gate  	/*****************************************************************/
957*0Sstevel@tonic-gate 	/* Read extentions config file                                   */
958*0Sstevel@tonic-gate 	if (extfile)
959*0Sstevel@tonic-gate 		{
960*0Sstevel@tonic-gate 		extconf = NCONF_new(NULL);
961*0Sstevel@tonic-gate 		if (NCONF_load(extconf,extfile,&errorline) <= 0)
962*0Sstevel@tonic-gate 			{
963*0Sstevel@tonic-gate 			if (errorline <= 0)
964*0Sstevel@tonic-gate 				BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
965*0Sstevel@tonic-gate 					extfile);
966*0Sstevel@tonic-gate 			else
967*0Sstevel@tonic-gate 				BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
968*0Sstevel@tonic-gate 					errorline,extfile);
969*0Sstevel@tonic-gate 			ret = 1;
970*0Sstevel@tonic-gate 			goto err;
971*0Sstevel@tonic-gate 			}
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate 		if (verbose)
974*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
975*0Sstevel@tonic-gate 
976*0Sstevel@tonic-gate 		/* We can have sections in the ext file */
977*0Sstevel@tonic-gate 		if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
978*0Sstevel@tonic-gate 			extensions = "default";
979*0Sstevel@tonic-gate 		}
980*0Sstevel@tonic-gate 
981*0Sstevel@tonic-gate 	/*****************************************************************/
982*0Sstevel@tonic-gate 	if (req || gencrl)
983*0Sstevel@tonic-gate 		{
984*0Sstevel@tonic-gate 		if (outfile != NULL)
985*0Sstevel@tonic-gate 			{
986*0Sstevel@tonic-gate 			if (BIO_write_filename(Sout,outfile) <= 0)
987*0Sstevel@tonic-gate 				{
988*0Sstevel@tonic-gate 				perror(outfile);
989*0Sstevel@tonic-gate 				goto err;
990*0Sstevel@tonic-gate 				}
991*0Sstevel@tonic-gate 			}
992*0Sstevel@tonic-gate 		else
993*0Sstevel@tonic-gate 			{
994*0Sstevel@tonic-gate 			BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
995*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
996*0Sstevel@tonic-gate 			{
997*0Sstevel@tonic-gate 			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
998*0Sstevel@tonic-gate 			Sout = BIO_push(tmpbio, Sout);
999*0Sstevel@tonic-gate 			}
1000*0Sstevel@tonic-gate #endif
1001*0Sstevel@tonic-gate 			}
1002*0Sstevel@tonic-gate 		}
1003*0Sstevel@tonic-gate 
1004*0Sstevel@tonic-gate 	if (req)
1005*0Sstevel@tonic-gate 		{
1006*0Sstevel@tonic-gate 		if ((md == NULL) && ((md=NCONF_get_string(conf,
1007*0Sstevel@tonic-gate 			section,ENV_DEFAULT_MD)) == NULL))
1008*0Sstevel@tonic-gate 			{
1009*0Sstevel@tonic-gate 			lookup_fail(section,ENV_DEFAULT_MD);
1010*0Sstevel@tonic-gate 			goto err;
1011*0Sstevel@tonic-gate 			}
1012*0Sstevel@tonic-gate 		if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1013*0Sstevel@tonic-gate 			section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1014*0Sstevel@tonic-gate 			{
1015*0Sstevel@tonic-gate 			if(strcmp(tmp_email_dn,"no") == 0)
1016*0Sstevel@tonic-gate 				email_dn=0;
1017*0Sstevel@tonic-gate 			}
1018*0Sstevel@tonic-gate 		if ((dgst=EVP_get_digestbyname(md)) == NULL)
1019*0Sstevel@tonic-gate 			{
1020*0Sstevel@tonic-gate 			BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1021*0Sstevel@tonic-gate 			goto err;
1022*0Sstevel@tonic-gate 			}
1023*0Sstevel@tonic-gate 		if (verbose)
1024*0Sstevel@tonic-gate 			BIO_printf(bio_err,"message digest is %s\n",
1025*0Sstevel@tonic-gate 				OBJ_nid2ln(dgst->type));
1026*0Sstevel@tonic-gate 		if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1027*0Sstevel@tonic-gate 			section,ENV_POLICY)) == NULL))
1028*0Sstevel@tonic-gate 			{
1029*0Sstevel@tonic-gate 			lookup_fail(section,ENV_POLICY);
1030*0Sstevel@tonic-gate 			goto err;
1031*0Sstevel@tonic-gate 			}
1032*0Sstevel@tonic-gate 		if (verbose)
1033*0Sstevel@tonic-gate 			BIO_printf(bio_err,"policy is %s\n",policy);
1034*0Sstevel@tonic-gate 
1035*0Sstevel@tonic-gate 		if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1036*0Sstevel@tonic-gate 			== NULL)
1037*0Sstevel@tonic-gate 			{
1038*0Sstevel@tonic-gate 			lookup_fail(section,ENV_SERIAL);
1039*0Sstevel@tonic-gate 			goto err;
1040*0Sstevel@tonic-gate 			}
1041*0Sstevel@tonic-gate 
1042*0Sstevel@tonic-gate 		if (!extconf)
1043*0Sstevel@tonic-gate 			{
1044*0Sstevel@tonic-gate 			/* no '-extfile' option, so we look for extensions
1045*0Sstevel@tonic-gate 			 * in the main configuration file */
1046*0Sstevel@tonic-gate 			if (!extensions)
1047*0Sstevel@tonic-gate 				{
1048*0Sstevel@tonic-gate 				extensions=NCONF_get_string(conf,section,
1049*0Sstevel@tonic-gate 								ENV_EXTENSIONS);
1050*0Sstevel@tonic-gate 				if (!extensions)
1051*0Sstevel@tonic-gate 					ERR_clear_error();
1052*0Sstevel@tonic-gate 				}
1053*0Sstevel@tonic-gate 			if (extensions)
1054*0Sstevel@tonic-gate 				{
1055*0Sstevel@tonic-gate 				/* Check syntax of file */
1056*0Sstevel@tonic-gate 				X509V3_CTX ctx;
1057*0Sstevel@tonic-gate 				X509V3_set_ctx_test(&ctx);
1058*0Sstevel@tonic-gate 				X509V3_set_nconf(&ctx, conf);
1059*0Sstevel@tonic-gate 				if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1060*0Sstevel@tonic-gate 								NULL))
1061*0Sstevel@tonic-gate 					{
1062*0Sstevel@tonic-gate 					BIO_printf(bio_err,
1063*0Sstevel@tonic-gate 				 	"Error Loading extension section %s\n",
1064*0Sstevel@tonic-gate 								 extensions);
1065*0Sstevel@tonic-gate 					ret = 1;
1066*0Sstevel@tonic-gate 					goto err;
1067*0Sstevel@tonic-gate 					}
1068*0Sstevel@tonic-gate 				}
1069*0Sstevel@tonic-gate 			}
1070*0Sstevel@tonic-gate 
1071*0Sstevel@tonic-gate 		if (startdate == NULL)
1072*0Sstevel@tonic-gate 			{
1073*0Sstevel@tonic-gate 			startdate=NCONF_get_string(conf,section,
1074*0Sstevel@tonic-gate 				ENV_DEFAULT_STARTDATE);
1075*0Sstevel@tonic-gate 			if (startdate == NULL)
1076*0Sstevel@tonic-gate 				ERR_clear_error();
1077*0Sstevel@tonic-gate 			}
1078*0Sstevel@tonic-gate 		if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1079*0Sstevel@tonic-gate 			{
1080*0Sstevel@tonic-gate 			BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1081*0Sstevel@tonic-gate 			goto err;
1082*0Sstevel@tonic-gate 			}
1083*0Sstevel@tonic-gate 		if (startdate == NULL) startdate="today";
1084*0Sstevel@tonic-gate 
1085*0Sstevel@tonic-gate 		if (enddate == NULL)
1086*0Sstevel@tonic-gate 			{
1087*0Sstevel@tonic-gate 			enddate=NCONF_get_string(conf,section,
1088*0Sstevel@tonic-gate 				ENV_DEFAULT_ENDDATE);
1089*0Sstevel@tonic-gate 			if (enddate == NULL)
1090*0Sstevel@tonic-gate 				ERR_clear_error();
1091*0Sstevel@tonic-gate 			}
1092*0Sstevel@tonic-gate 		if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1093*0Sstevel@tonic-gate 			{
1094*0Sstevel@tonic-gate 			BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1095*0Sstevel@tonic-gate 			goto err;
1096*0Sstevel@tonic-gate 			}
1097*0Sstevel@tonic-gate 
1098*0Sstevel@tonic-gate 		if (days == 0)
1099*0Sstevel@tonic-gate 			{
1100*0Sstevel@tonic-gate 			if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1101*0Sstevel@tonic-gate 				days = 0;
1102*0Sstevel@tonic-gate 			}
1103*0Sstevel@tonic-gate 		if (!enddate && (days == 0))
1104*0Sstevel@tonic-gate 			{
1105*0Sstevel@tonic-gate 			BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1106*0Sstevel@tonic-gate 			goto err;
1107*0Sstevel@tonic-gate 			}
1108*0Sstevel@tonic-gate 
1109*0Sstevel@tonic-gate 		if ((serial=load_serial(serialfile, 0, NULL)) == NULL)
1110*0Sstevel@tonic-gate 			{
1111*0Sstevel@tonic-gate 			BIO_printf(bio_err,"error while loading serial number\n");
1112*0Sstevel@tonic-gate 			goto err;
1113*0Sstevel@tonic-gate 			}
1114*0Sstevel@tonic-gate 		if (verbose)
1115*0Sstevel@tonic-gate 			{
1116*0Sstevel@tonic-gate 			if (BN_is_zero(serial))
1117*0Sstevel@tonic-gate 				BIO_printf(bio_err,"next serial number is 00\n");
1118*0Sstevel@tonic-gate 			else
1119*0Sstevel@tonic-gate 				{
1120*0Sstevel@tonic-gate 				if ((f=BN_bn2hex(serial)) == NULL) goto err;
1121*0Sstevel@tonic-gate 				BIO_printf(bio_err,"next serial number is %s\n",f);
1122*0Sstevel@tonic-gate 				OPENSSL_free(f);
1123*0Sstevel@tonic-gate 				}
1124*0Sstevel@tonic-gate 			}
1125*0Sstevel@tonic-gate 
1126*0Sstevel@tonic-gate 		if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1127*0Sstevel@tonic-gate 			{
1128*0Sstevel@tonic-gate 			BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1129*0Sstevel@tonic-gate 			goto err;
1130*0Sstevel@tonic-gate 			}
1131*0Sstevel@tonic-gate 
1132*0Sstevel@tonic-gate 		if ((cert_sk=sk_X509_new_null()) == NULL)
1133*0Sstevel@tonic-gate 			{
1134*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Memory allocation failure\n");
1135*0Sstevel@tonic-gate 			goto err;
1136*0Sstevel@tonic-gate 			}
1137*0Sstevel@tonic-gate 		if (spkac_file != NULL)
1138*0Sstevel@tonic-gate 			{
1139*0Sstevel@tonic-gate 			total++;
1140*0Sstevel@tonic-gate 			j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1141*0Sstevel@tonic-gate 				serial,subj,email_dn,startdate,enddate,days,extensions,
1142*0Sstevel@tonic-gate 				conf,verbose,certopt,nameopt,default_op,ext_copy);
1143*0Sstevel@tonic-gate 			if (j < 0) goto err;
1144*0Sstevel@tonic-gate 			if (j > 0)
1145*0Sstevel@tonic-gate 				{
1146*0Sstevel@tonic-gate 				total_done++;
1147*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\n");
1148*0Sstevel@tonic-gate 				if (!BN_add_word(serial,1)) goto err;
1149*0Sstevel@tonic-gate 				if (!sk_X509_push(cert_sk,x))
1150*0Sstevel@tonic-gate 					{
1151*0Sstevel@tonic-gate 					BIO_printf(bio_err,"Memory allocation failure\n");
1152*0Sstevel@tonic-gate 					goto err;
1153*0Sstevel@tonic-gate 					}
1154*0Sstevel@tonic-gate 				if (outfile)
1155*0Sstevel@tonic-gate 					{
1156*0Sstevel@tonic-gate 					output_der = 1;
1157*0Sstevel@tonic-gate 					batch = 1;
1158*0Sstevel@tonic-gate 					}
1159*0Sstevel@tonic-gate 				}
1160*0Sstevel@tonic-gate 			}
1161*0Sstevel@tonic-gate 		if (ss_cert_file != NULL)
1162*0Sstevel@tonic-gate 			{
1163*0Sstevel@tonic-gate 			total++;
1164*0Sstevel@tonic-gate 			j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1165*0Sstevel@tonic-gate 				db,serial,subj,email_dn,startdate,enddate,days,batch,
1166*0Sstevel@tonic-gate 				extensions,conf,verbose, certopt, nameopt,
1167*0Sstevel@tonic-gate 				default_op, ext_copy, e);
1168*0Sstevel@tonic-gate 			if (j < 0) goto err;
1169*0Sstevel@tonic-gate 			if (j > 0)
1170*0Sstevel@tonic-gate 				{
1171*0Sstevel@tonic-gate 				total_done++;
1172*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\n");
1173*0Sstevel@tonic-gate 				if (!BN_add_word(serial,1)) goto err;
1174*0Sstevel@tonic-gate 				if (!sk_X509_push(cert_sk,x))
1175*0Sstevel@tonic-gate 					{
1176*0Sstevel@tonic-gate 					BIO_printf(bio_err,"Memory allocation failure\n");
1177*0Sstevel@tonic-gate 					goto err;
1178*0Sstevel@tonic-gate 					}
1179*0Sstevel@tonic-gate 				}
1180*0Sstevel@tonic-gate 			}
1181*0Sstevel@tonic-gate 		if (infile != NULL)
1182*0Sstevel@tonic-gate 			{
1183*0Sstevel@tonic-gate 			total++;
1184*0Sstevel@tonic-gate 			j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1185*0Sstevel@tonic-gate 				serial,subj,email_dn,startdate,enddate,days,batch,
1186*0Sstevel@tonic-gate 				extensions,conf,verbose, certopt, nameopt,
1187*0Sstevel@tonic-gate 				default_op, ext_copy);
1188*0Sstevel@tonic-gate 			if (j < 0) goto err;
1189*0Sstevel@tonic-gate 			if (j > 0)
1190*0Sstevel@tonic-gate 				{
1191*0Sstevel@tonic-gate 				total_done++;
1192*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\n");
1193*0Sstevel@tonic-gate 				if (!BN_add_word(serial,1)) goto err;
1194*0Sstevel@tonic-gate 				if (!sk_X509_push(cert_sk,x))
1195*0Sstevel@tonic-gate 					{
1196*0Sstevel@tonic-gate 					BIO_printf(bio_err,"Memory allocation failure\n");
1197*0Sstevel@tonic-gate 					goto err;
1198*0Sstevel@tonic-gate 					}
1199*0Sstevel@tonic-gate 				}
1200*0Sstevel@tonic-gate 			}
1201*0Sstevel@tonic-gate 		for (i=0; i<argc; i++)
1202*0Sstevel@tonic-gate 			{
1203*0Sstevel@tonic-gate 			total++;
1204*0Sstevel@tonic-gate 			j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1205*0Sstevel@tonic-gate 				serial,subj,email_dn,startdate,enddate,days,batch,
1206*0Sstevel@tonic-gate 				extensions,conf,verbose, certopt, nameopt,
1207*0Sstevel@tonic-gate 				default_op, ext_copy);
1208*0Sstevel@tonic-gate 			if (j < 0) goto err;
1209*0Sstevel@tonic-gate 			if (j > 0)
1210*0Sstevel@tonic-gate 				{
1211*0Sstevel@tonic-gate 				total_done++;
1212*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\n");
1213*0Sstevel@tonic-gate 				if (!BN_add_word(serial,1)) goto err;
1214*0Sstevel@tonic-gate 				if (!sk_X509_push(cert_sk,x))
1215*0Sstevel@tonic-gate 					{
1216*0Sstevel@tonic-gate 					BIO_printf(bio_err,"Memory allocation failure\n");
1217*0Sstevel@tonic-gate 					goto err;
1218*0Sstevel@tonic-gate 					}
1219*0Sstevel@tonic-gate 				}
1220*0Sstevel@tonic-gate 			}
1221*0Sstevel@tonic-gate 		/* we have a stack of newly certified certificates
1222*0Sstevel@tonic-gate 		 * and a data base and serial number that need
1223*0Sstevel@tonic-gate 		 * updating */
1224*0Sstevel@tonic-gate 
1225*0Sstevel@tonic-gate 		if (sk_X509_num(cert_sk) > 0)
1226*0Sstevel@tonic-gate 			{
1227*0Sstevel@tonic-gate 			if (!batch)
1228*0Sstevel@tonic-gate 				{
1229*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1230*0Sstevel@tonic-gate 				(void)BIO_flush(bio_err);
1231*0Sstevel@tonic-gate 				buf[0][0]='\0';
1232*0Sstevel@tonic-gate 				fgets(buf[0],10,stdin);
1233*0Sstevel@tonic-gate 				if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1234*0Sstevel@tonic-gate 					{
1235*0Sstevel@tonic-gate 					BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1236*0Sstevel@tonic-gate 					ret=0;
1237*0Sstevel@tonic-gate 					goto err;
1238*0Sstevel@tonic-gate 					}
1239*0Sstevel@tonic-gate 				}
1240*0Sstevel@tonic-gate 
1241*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1242*0Sstevel@tonic-gate 
1243*0Sstevel@tonic-gate 			if (!save_serial(serialfile,"new",serial,NULL)) goto err;
1244*0Sstevel@tonic-gate 
1245*0Sstevel@tonic-gate 			if (!save_index(dbfile, "new", db)) goto err;
1246*0Sstevel@tonic-gate 			}
1247*0Sstevel@tonic-gate 
1248*0Sstevel@tonic-gate 		if (verbose)
1249*0Sstevel@tonic-gate 			BIO_printf(bio_err,"writing new certificates\n");
1250*0Sstevel@tonic-gate 		for (i=0; i<sk_X509_num(cert_sk); i++)
1251*0Sstevel@tonic-gate 			{
1252*0Sstevel@tonic-gate 			int k;
1253*0Sstevel@tonic-gate 			char *n;
1254*0Sstevel@tonic-gate 
1255*0Sstevel@tonic-gate 			x=sk_X509_value(cert_sk,i);
1256*0Sstevel@tonic-gate 
1257*0Sstevel@tonic-gate 			j=x->cert_info->serialNumber->length;
1258*0Sstevel@tonic-gate 			p=(char *)x->cert_info->serialNumber->data;
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate 			if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1261*0Sstevel@tonic-gate 				{
1262*0Sstevel@tonic-gate 				BIO_printf(bio_err,"certificate file name too long\n");
1263*0Sstevel@tonic-gate 				goto err;
1264*0Sstevel@tonic-gate 				}
1265*0Sstevel@tonic-gate 
1266*0Sstevel@tonic-gate 			strcpy(buf[2],outdir);
1267*0Sstevel@tonic-gate 
1268*0Sstevel@tonic-gate #ifndef OPENSSL_SYS_VMS
1269*0Sstevel@tonic-gate 			BUF_strlcat(buf[2],"/",sizeof(buf[2]));
1270*0Sstevel@tonic-gate #endif
1271*0Sstevel@tonic-gate 
1272*0Sstevel@tonic-gate 			n=(char *)&(buf[2][strlen(buf[2])]);
1273*0Sstevel@tonic-gate 			if (j > 0)
1274*0Sstevel@tonic-gate 				{
1275*0Sstevel@tonic-gate 				for (k=0; k<j; k++)
1276*0Sstevel@tonic-gate 					{
1277*0Sstevel@tonic-gate 					if (n >= &(buf[2][sizeof(buf[2])]))
1278*0Sstevel@tonic-gate 						break;
1279*0Sstevel@tonic-gate 					BIO_snprintf(n,
1280*0Sstevel@tonic-gate 						     &buf[2][0] + sizeof(buf[2]) - n,
1281*0Sstevel@tonic-gate 						     "%02X",(unsigned char)*(p++));
1282*0Sstevel@tonic-gate 					n+=2;
1283*0Sstevel@tonic-gate 					}
1284*0Sstevel@tonic-gate 				}
1285*0Sstevel@tonic-gate 			else
1286*0Sstevel@tonic-gate 				{
1287*0Sstevel@tonic-gate 				*(n++)='0';
1288*0Sstevel@tonic-gate 				*(n++)='0';
1289*0Sstevel@tonic-gate 				}
1290*0Sstevel@tonic-gate 			*(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1291*0Sstevel@tonic-gate 			*n='\0';
1292*0Sstevel@tonic-gate 			if (verbose)
1293*0Sstevel@tonic-gate 				BIO_printf(bio_err,"writing %s\n",buf[2]);
1294*0Sstevel@tonic-gate 
1295*0Sstevel@tonic-gate 			if (BIO_write_filename(Cout,buf[2]) <= 0)
1296*0Sstevel@tonic-gate 				{
1297*0Sstevel@tonic-gate 				perror(buf[2]);
1298*0Sstevel@tonic-gate 				goto err;
1299*0Sstevel@tonic-gate 				}
1300*0Sstevel@tonic-gate 			write_new_certificate(Cout,x, 0, notext);
1301*0Sstevel@tonic-gate 			write_new_certificate(Sout,x, output_der, notext);
1302*0Sstevel@tonic-gate 			}
1303*0Sstevel@tonic-gate 
1304*0Sstevel@tonic-gate 		if (sk_X509_num(cert_sk))
1305*0Sstevel@tonic-gate 			{
1306*0Sstevel@tonic-gate 			/* Rename the database and the serial file */
1307*0Sstevel@tonic-gate 			if (!rotate_serial(serialfile,"new","old")) goto err;
1308*0Sstevel@tonic-gate 
1309*0Sstevel@tonic-gate 			if (!rotate_index(dbfile,"new","old")) goto err;
1310*0Sstevel@tonic-gate 
1311*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Data Base Updated\n");
1312*0Sstevel@tonic-gate 			}
1313*0Sstevel@tonic-gate 		}
1314*0Sstevel@tonic-gate 
1315*0Sstevel@tonic-gate 	/*****************************************************************/
1316*0Sstevel@tonic-gate 	if (gencrl)
1317*0Sstevel@tonic-gate 		{
1318*0Sstevel@tonic-gate 		int crl_v2 = 0;
1319*0Sstevel@tonic-gate 		if (!crl_ext)
1320*0Sstevel@tonic-gate 			{
1321*0Sstevel@tonic-gate 			crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1322*0Sstevel@tonic-gate 			if (!crl_ext)
1323*0Sstevel@tonic-gate 				ERR_clear_error();
1324*0Sstevel@tonic-gate 			}
1325*0Sstevel@tonic-gate 		if (crl_ext)
1326*0Sstevel@tonic-gate 			{
1327*0Sstevel@tonic-gate 			/* Check syntax of file */
1328*0Sstevel@tonic-gate 			X509V3_CTX ctx;
1329*0Sstevel@tonic-gate 			X509V3_set_ctx_test(&ctx);
1330*0Sstevel@tonic-gate 			X509V3_set_nconf(&ctx, conf);
1331*0Sstevel@tonic-gate 			if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1332*0Sstevel@tonic-gate 				{
1333*0Sstevel@tonic-gate 				BIO_printf(bio_err,
1334*0Sstevel@tonic-gate 				 "Error Loading CRL extension section %s\n",
1335*0Sstevel@tonic-gate 								 crl_ext);
1336*0Sstevel@tonic-gate 				ret = 1;
1337*0Sstevel@tonic-gate 				goto err;
1338*0Sstevel@tonic-gate 				}
1339*0Sstevel@tonic-gate 			}
1340*0Sstevel@tonic-gate 
1341*0Sstevel@tonic-gate 		if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
1342*0Sstevel@tonic-gate 			!= NULL)
1343*0Sstevel@tonic-gate 			if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
1344*0Sstevel@tonic-gate 				{
1345*0Sstevel@tonic-gate 				BIO_printf(bio_err,"error while loading CRL number\n");
1346*0Sstevel@tonic-gate 				goto err;
1347*0Sstevel@tonic-gate 				}
1348*0Sstevel@tonic-gate 
1349*0Sstevel@tonic-gate 		if (!crldays && !crlhours)
1350*0Sstevel@tonic-gate 			{
1351*0Sstevel@tonic-gate 			if (!NCONF_get_number(conf,section,
1352*0Sstevel@tonic-gate 				ENV_DEFAULT_CRL_DAYS, &crldays))
1353*0Sstevel@tonic-gate 				crldays = 0;
1354*0Sstevel@tonic-gate 			if (!NCONF_get_number(conf,section,
1355*0Sstevel@tonic-gate 				ENV_DEFAULT_CRL_HOURS, &crlhours))
1356*0Sstevel@tonic-gate 				crlhours = 0;
1357*0Sstevel@tonic-gate 			}
1358*0Sstevel@tonic-gate 		if ((crldays == 0) && (crlhours == 0))
1359*0Sstevel@tonic-gate 			{
1360*0Sstevel@tonic-gate 			BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
1361*0Sstevel@tonic-gate 			goto err;
1362*0Sstevel@tonic-gate 			}
1363*0Sstevel@tonic-gate 
1364*0Sstevel@tonic-gate 		if (verbose) BIO_printf(bio_err,"making CRL\n");
1365*0Sstevel@tonic-gate 		if ((crl=X509_CRL_new()) == NULL) goto err;
1366*0Sstevel@tonic-gate 		if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
1367*0Sstevel@tonic-gate 
1368*0Sstevel@tonic-gate 		tmptm = ASN1_TIME_new();
1369*0Sstevel@tonic-gate 		if (!tmptm) goto err;
1370*0Sstevel@tonic-gate 		X509_gmtime_adj(tmptm,0);
1371*0Sstevel@tonic-gate 		X509_CRL_set_lastUpdate(crl, tmptm);
1372*0Sstevel@tonic-gate 		X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1373*0Sstevel@tonic-gate 		X509_CRL_set_nextUpdate(crl, tmptm);
1374*0Sstevel@tonic-gate 
1375*0Sstevel@tonic-gate 		ASN1_TIME_free(tmptm);
1376*0Sstevel@tonic-gate 
1377*0Sstevel@tonic-gate 		for (i=0; i<sk_num(db->db->data); i++)
1378*0Sstevel@tonic-gate 			{
1379*0Sstevel@tonic-gate 			pp=(char **)sk_value(db->db->data,i);
1380*0Sstevel@tonic-gate 			if (pp[DB_type][0] == DB_TYPE_REV)
1381*0Sstevel@tonic-gate 				{
1382*0Sstevel@tonic-gate 				if ((r=X509_REVOKED_new()) == NULL) goto err;
1383*0Sstevel@tonic-gate 				j = make_revoked(r, pp[DB_rev_date]);
1384*0Sstevel@tonic-gate 				if (!j) goto err;
1385*0Sstevel@tonic-gate 				if (j == 2) crl_v2 = 1;
1386*0Sstevel@tonic-gate 				if (!BN_hex2bn(&serial, pp[DB_serial]))
1387*0Sstevel@tonic-gate 					goto err;
1388*0Sstevel@tonic-gate 				tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1389*0Sstevel@tonic-gate 				BN_free(serial);
1390*0Sstevel@tonic-gate 				serial = NULL;
1391*0Sstevel@tonic-gate 				if (!tmpser)
1392*0Sstevel@tonic-gate 					goto err;
1393*0Sstevel@tonic-gate 				X509_REVOKED_set_serialNumber(r, tmpser);
1394*0Sstevel@tonic-gate 				ASN1_INTEGER_free(tmpser);
1395*0Sstevel@tonic-gate 				X509_CRL_add0_revoked(crl,r);
1396*0Sstevel@tonic-gate 				}
1397*0Sstevel@tonic-gate 			}
1398*0Sstevel@tonic-gate 
1399*0Sstevel@tonic-gate 		/* sort the data so it will be written in serial
1400*0Sstevel@tonic-gate 		 * number order */
1401*0Sstevel@tonic-gate 		X509_CRL_sort(crl);
1402*0Sstevel@tonic-gate 
1403*0Sstevel@tonic-gate 		/* we now have a CRL */
1404*0Sstevel@tonic-gate 		if (verbose) BIO_printf(bio_err,"signing CRL\n");
1405*0Sstevel@tonic-gate 		if (md != NULL)
1406*0Sstevel@tonic-gate 			{
1407*0Sstevel@tonic-gate 			if ((dgst=EVP_get_digestbyname(md)) == NULL)
1408*0Sstevel@tonic-gate 				{
1409*0Sstevel@tonic-gate 				BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1410*0Sstevel@tonic-gate 				goto err;
1411*0Sstevel@tonic-gate 				}
1412*0Sstevel@tonic-gate 			}
1413*0Sstevel@tonic-gate 		else
1414*0Sstevel@tonic-gate 			{
1415*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
1416*0Sstevel@tonic-gate 			if (pkey->type == EVP_PKEY_DSA)
1417*0Sstevel@tonic-gate 				dgst=EVP_dss1();
1418*0Sstevel@tonic-gate 			else
1419*0Sstevel@tonic-gate #endif
1420*0Sstevel@tonic-gate 				dgst=EVP_md5();
1421*0Sstevel@tonic-gate 			}
1422*0Sstevel@tonic-gate 
1423*0Sstevel@tonic-gate 		/* Add any extensions asked for */
1424*0Sstevel@tonic-gate 
1425*0Sstevel@tonic-gate 		if (crl_ext || crlnumberfile != NULL)
1426*0Sstevel@tonic-gate 			{
1427*0Sstevel@tonic-gate 			X509V3_CTX crlctx;
1428*0Sstevel@tonic-gate 			X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1429*0Sstevel@tonic-gate 			X509V3_set_nconf(&crlctx, conf);
1430*0Sstevel@tonic-gate 
1431*0Sstevel@tonic-gate 			if (crl_ext)
1432*0Sstevel@tonic-gate 				if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1433*0Sstevel@tonic-gate 					crl_ext, crl)) goto err;
1434*0Sstevel@tonic-gate 			if (crlnumberfile != NULL)
1435*0Sstevel@tonic-gate 				{
1436*0Sstevel@tonic-gate 				tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1437*0Sstevel@tonic-gate 				if (!tmpser) goto err;
1438*0Sstevel@tonic-gate 				X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
1439*0Sstevel@tonic-gate 				ASN1_INTEGER_free(tmpser);
1440*0Sstevel@tonic-gate 				crl_v2 = 1;
1441*0Sstevel@tonic-gate 				if (!BN_add_word(crlnumber,1)) goto err;
1442*0Sstevel@tonic-gate 				}
1443*0Sstevel@tonic-gate 			}
1444*0Sstevel@tonic-gate 		if (crl_ext || crl_v2)
1445*0Sstevel@tonic-gate 			{
1446*0Sstevel@tonic-gate 			if (!X509_CRL_set_version(crl, 1))
1447*0Sstevel@tonic-gate 				goto err; /* version 2 CRL */
1448*0Sstevel@tonic-gate 			}
1449*0Sstevel@tonic-gate 
1450*0Sstevel@tonic-gate 
1451*0Sstevel@tonic-gate 		if (crlnumberfile != NULL)	/* we have a CRL number that need updating */
1452*0Sstevel@tonic-gate 			if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
1453*0Sstevel@tonic-gate 
1454*0Sstevel@tonic-gate 		if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1455*0Sstevel@tonic-gate 
1456*0Sstevel@tonic-gate 		PEM_write_bio_X509_CRL(Sout,crl);
1457*0Sstevel@tonic-gate 
1458*0Sstevel@tonic-gate 		if (crlnumberfile != NULL)	/* Rename the crlnumber file */
1459*0Sstevel@tonic-gate 			if (!rotate_serial(crlnumberfile,"new","old")) goto err;
1460*0Sstevel@tonic-gate 
1461*0Sstevel@tonic-gate 		}
1462*0Sstevel@tonic-gate 	/*****************************************************************/
1463*0Sstevel@tonic-gate 	if (dorevoke)
1464*0Sstevel@tonic-gate 		{
1465*0Sstevel@tonic-gate 		if (infile == NULL)
1466*0Sstevel@tonic-gate 			{
1467*0Sstevel@tonic-gate 			BIO_printf(bio_err,"no input files\n");
1468*0Sstevel@tonic-gate 			goto err;
1469*0Sstevel@tonic-gate 			}
1470*0Sstevel@tonic-gate 		else
1471*0Sstevel@tonic-gate 			{
1472*0Sstevel@tonic-gate 			X509 *revcert;
1473*0Sstevel@tonic-gate 			revcert=load_cert(bio_err, infile, FORMAT_PEM,
1474*0Sstevel@tonic-gate 				NULL, e, infile);
1475*0Sstevel@tonic-gate 			if (revcert == NULL)
1476*0Sstevel@tonic-gate 				goto err;
1477*0Sstevel@tonic-gate 			j=do_revoke(revcert,db, rev_type, rev_arg);
1478*0Sstevel@tonic-gate 			if (j <= 0) goto err;
1479*0Sstevel@tonic-gate 			X509_free(revcert);
1480*0Sstevel@tonic-gate 
1481*0Sstevel@tonic-gate 			if (!save_index(dbfile, "new", db)) goto err;
1482*0Sstevel@tonic-gate 
1483*0Sstevel@tonic-gate 			if (!rotate_index(dbfile, "new", "old")) goto err;
1484*0Sstevel@tonic-gate 
1485*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Data Base Updated\n");
1486*0Sstevel@tonic-gate 			}
1487*0Sstevel@tonic-gate 		}
1488*0Sstevel@tonic-gate 	/*****************************************************************/
1489*0Sstevel@tonic-gate 	ret=0;
1490*0Sstevel@tonic-gate err:
1491*0Sstevel@tonic-gate 	if(tofree)
1492*0Sstevel@tonic-gate 		OPENSSL_free(tofree);
1493*0Sstevel@tonic-gate 	BIO_free_all(Cout);
1494*0Sstevel@tonic-gate 	BIO_free_all(Sout);
1495*0Sstevel@tonic-gate 	BIO_free_all(out);
1496*0Sstevel@tonic-gate 	BIO_free_all(in);
1497*0Sstevel@tonic-gate 
1498*0Sstevel@tonic-gate 	if (cert_sk)
1499*0Sstevel@tonic-gate 		sk_X509_pop_free(cert_sk,X509_free);
1500*0Sstevel@tonic-gate 
1501*0Sstevel@tonic-gate 	if (ret) ERR_print_errors(bio_err);
1502*0Sstevel@tonic-gate 	app_RAND_write_file(randfile, bio_err);
1503*0Sstevel@tonic-gate 	if (free_key && key)
1504*0Sstevel@tonic-gate 		OPENSSL_free(key);
1505*0Sstevel@tonic-gate 	BN_free(serial);
1506*0Sstevel@tonic-gate 	if (db)
1507*0Sstevel@tonic-gate 		free_index(db);
1508*0Sstevel@tonic-gate 	EVP_PKEY_free(pkey);
1509*0Sstevel@tonic-gate 	X509_free(x509);
1510*0Sstevel@tonic-gate 	X509_CRL_free(crl);
1511*0Sstevel@tonic-gate 	NCONF_free(conf);
1512*0Sstevel@tonic-gate 	OBJ_cleanup();
1513*0Sstevel@tonic-gate 	apps_shutdown();
1514*0Sstevel@tonic-gate 	OPENSSL_EXIT(ret);
1515*0Sstevel@tonic-gate 	}
1516*0Sstevel@tonic-gate 
1517*0Sstevel@tonic-gate static void lookup_fail(char *name, char *tag)
1518*0Sstevel@tonic-gate 	{
1519*0Sstevel@tonic-gate 	BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1520*0Sstevel@tonic-gate 	}
1521*0Sstevel@tonic-gate 
1522*0Sstevel@tonic-gate static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1523*0Sstevel@tonic-gate 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1524*0Sstevel@tonic-gate 	     BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1525*0Sstevel@tonic-gate 	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1526*0Sstevel@tonic-gate 	     unsigned long certopt, unsigned long nameopt, int default_op,
1527*0Sstevel@tonic-gate 	     int ext_copy)
1528*0Sstevel@tonic-gate 	{
1529*0Sstevel@tonic-gate 	X509_REQ *req=NULL;
1530*0Sstevel@tonic-gate 	BIO *in=NULL;
1531*0Sstevel@tonic-gate 	EVP_PKEY *pktmp=NULL;
1532*0Sstevel@tonic-gate 	int ok= -1,i;
1533*0Sstevel@tonic-gate 
1534*0Sstevel@tonic-gate 	in=BIO_new(BIO_s_file());
1535*0Sstevel@tonic-gate 
1536*0Sstevel@tonic-gate 	if (BIO_read_filename(in,infile) <= 0)
1537*0Sstevel@tonic-gate 		{
1538*0Sstevel@tonic-gate 		perror(infile);
1539*0Sstevel@tonic-gate 		goto err;
1540*0Sstevel@tonic-gate 		}
1541*0Sstevel@tonic-gate 	if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1542*0Sstevel@tonic-gate 		{
1543*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Error reading certificate request in %s\n",
1544*0Sstevel@tonic-gate 			infile);
1545*0Sstevel@tonic-gate 		goto err;
1546*0Sstevel@tonic-gate 		}
1547*0Sstevel@tonic-gate 	if (verbose)
1548*0Sstevel@tonic-gate 		X509_REQ_print(bio_err,req);
1549*0Sstevel@tonic-gate 
1550*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Check that the request matches the signature\n");
1551*0Sstevel@tonic-gate 
1552*0Sstevel@tonic-gate 	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1553*0Sstevel@tonic-gate 		{
1554*0Sstevel@tonic-gate 		BIO_printf(bio_err,"error unpacking public key\n");
1555*0Sstevel@tonic-gate 		goto err;
1556*0Sstevel@tonic-gate 		}
1557*0Sstevel@tonic-gate 	i=X509_REQ_verify(req,pktmp);
1558*0Sstevel@tonic-gate 	EVP_PKEY_free(pktmp);
1559*0Sstevel@tonic-gate 	if (i < 0)
1560*0Sstevel@tonic-gate 		{
1561*0Sstevel@tonic-gate 		ok=0;
1562*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature verification problems....\n");
1563*0Sstevel@tonic-gate 		goto err;
1564*0Sstevel@tonic-gate 		}
1565*0Sstevel@tonic-gate 	if (i == 0)
1566*0Sstevel@tonic-gate 		{
1567*0Sstevel@tonic-gate 		ok=0;
1568*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature did not match the certificate request\n");
1569*0Sstevel@tonic-gate 		goto err;
1570*0Sstevel@tonic-gate 		}
1571*0Sstevel@tonic-gate 	else
1572*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature ok\n");
1573*0Sstevel@tonic-gate 
1574*0Sstevel@tonic-gate 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
1575*0Sstevel@tonic-gate 		startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1576*0Sstevel@tonic-gate 		certopt, nameopt, default_op, ext_copy);
1577*0Sstevel@tonic-gate 
1578*0Sstevel@tonic-gate err:
1579*0Sstevel@tonic-gate 	if (req != NULL) X509_REQ_free(req);
1580*0Sstevel@tonic-gate 	if (in != NULL) BIO_free(in);
1581*0Sstevel@tonic-gate 	return(ok);
1582*0Sstevel@tonic-gate 	}
1583*0Sstevel@tonic-gate 
1584*0Sstevel@tonic-gate static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1585*0Sstevel@tonic-gate 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1586*0Sstevel@tonic-gate 	     BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
1587*0Sstevel@tonic-gate 	     long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1588*0Sstevel@tonic-gate 	     unsigned long certopt, unsigned long nameopt, int default_op,
1589*0Sstevel@tonic-gate 	     int ext_copy, ENGINE *e)
1590*0Sstevel@tonic-gate 	{
1591*0Sstevel@tonic-gate 	X509 *req=NULL;
1592*0Sstevel@tonic-gate 	X509_REQ *rreq=NULL;
1593*0Sstevel@tonic-gate 	EVP_PKEY *pktmp=NULL;
1594*0Sstevel@tonic-gate 	int ok= -1,i;
1595*0Sstevel@tonic-gate 
1596*0Sstevel@tonic-gate 	if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1597*0Sstevel@tonic-gate 		goto err;
1598*0Sstevel@tonic-gate 	if (verbose)
1599*0Sstevel@tonic-gate 		X509_print(bio_err,req);
1600*0Sstevel@tonic-gate 
1601*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Check that the request matches the signature\n");
1602*0Sstevel@tonic-gate 
1603*0Sstevel@tonic-gate 	if ((pktmp=X509_get_pubkey(req)) == NULL)
1604*0Sstevel@tonic-gate 		{
1605*0Sstevel@tonic-gate 		BIO_printf(bio_err,"error unpacking public key\n");
1606*0Sstevel@tonic-gate 		goto err;
1607*0Sstevel@tonic-gate 		}
1608*0Sstevel@tonic-gate 	i=X509_verify(req,pktmp);
1609*0Sstevel@tonic-gate 	EVP_PKEY_free(pktmp);
1610*0Sstevel@tonic-gate 	if (i < 0)
1611*0Sstevel@tonic-gate 		{
1612*0Sstevel@tonic-gate 		ok=0;
1613*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature verification problems....\n");
1614*0Sstevel@tonic-gate 		goto err;
1615*0Sstevel@tonic-gate 		}
1616*0Sstevel@tonic-gate 	if (i == 0)
1617*0Sstevel@tonic-gate 		{
1618*0Sstevel@tonic-gate 		ok=0;
1619*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature did not match the certificate\n");
1620*0Sstevel@tonic-gate 		goto err;
1621*0Sstevel@tonic-gate 		}
1622*0Sstevel@tonic-gate 	else
1623*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Signature ok\n");
1624*0Sstevel@tonic-gate 
1625*0Sstevel@tonic-gate 	if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1626*0Sstevel@tonic-gate 		goto err;
1627*0Sstevel@tonic-gate 
1628*0Sstevel@tonic-gate 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
1629*0Sstevel@tonic-gate 		days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1630*0Sstevel@tonic-gate 		ext_copy);
1631*0Sstevel@tonic-gate 
1632*0Sstevel@tonic-gate err:
1633*0Sstevel@tonic-gate 	if (rreq != NULL) X509_REQ_free(rreq);
1634*0Sstevel@tonic-gate 	if (req != NULL) X509_free(req);
1635*0Sstevel@tonic-gate 	return(ok);
1636*0Sstevel@tonic-gate 	}
1637*0Sstevel@tonic-gate 
1638*0Sstevel@tonic-gate static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1639*0Sstevel@tonic-gate 	     STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
1640*0Sstevel@tonic-gate 	     int email_dn, char *startdate, char *enddate, long days, int batch,
1641*0Sstevel@tonic-gate 	     int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1642*0Sstevel@tonic-gate 	     unsigned long certopt, unsigned long nameopt, int default_op,
1643*0Sstevel@tonic-gate 	     int ext_copy)
1644*0Sstevel@tonic-gate 	{
1645*0Sstevel@tonic-gate 	X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
1646*0Sstevel@tonic-gate 	ASN1_UTCTIME *tm,*tmptm;
1647*0Sstevel@tonic-gate 	ASN1_STRING *str,*str2;
1648*0Sstevel@tonic-gate 	ASN1_OBJECT *obj;
1649*0Sstevel@tonic-gate 	X509 *ret=NULL;
1650*0Sstevel@tonic-gate 	X509_CINF *ci;
1651*0Sstevel@tonic-gate 	X509_NAME_ENTRY *ne;
1652*0Sstevel@tonic-gate 	X509_NAME_ENTRY *tne,*push;
1653*0Sstevel@tonic-gate 	EVP_PKEY *pktmp;
1654*0Sstevel@tonic-gate 	int ok= -1,i,j,last,nid;
1655*0Sstevel@tonic-gate 	char *p;
1656*0Sstevel@tonic-gate 	CONF_VALUE *cv;
1657*0Sstevel@tonic-gate 	char *row[DB_NUMBER],**rrow=NULL,**irow=NULL;
1658*0Sstevel@tonic-gate 	char buf[25];
1659*0Sstevel@tonic-gate 
1660*0Sstevel@tonic-gate 	tmptm=ASN1_UTCTIME_new();
1661*0Sstevel@tonic-gate 	if (tmptm == NULL)
1662*0Sstevel@tonic-gate 		{
1663*0Sstevel@tonic-gate 		BIO_printf(bio_err,"malloc error\n");
1664*0Sstevel@tonic-gate 		return(0);
1665*0Sstevel@tonic-gate 		}
1666*0Sstevel@tonic-gate 
1667*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
1668*0Sstevel@tonic-gate 		row[i]=NULL;
1669*0Sstevel@tonic-gate 
1670*0Sstevel@tonic-gate 	if (subj)
1671*0Sstevel@tonic-gate 		{
1672*0Sstevel@tonic-gate 		X509_NAME *n = do_subject(subj, MBSTRING_ASC);
1673*0Sstevel@tonic-gate 
1674*0Sstevel@tonic-gate 		if (!n)
1675*0Sstevel@tonic-gate 			{
1676*0Sstevel@tonic-gate 			ERR_print_errors(bio_err);
1677*0Sstevel@tonic-gate 			goto err;
1678*0Sstevel@tonic-gate 			}
1679*0Sstevel@tonic-gate 		X509_REQ_set_subject_name(req,n);
1680*0Sstevel@tonic-gate 		req->req_info->enc.modified = 1;
1681*0Sstevel@tonic-gate 		X509_NAME_free(n);
1682*0Sstevel@tonic-gate 		}
1683*0Sstevel@tonic-gate 
1684*0Sstevel@tonic-gate 	if (default_op)
1685*0Sstevel@tonic-gate 		BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1686*0Sstevel@tonic-gate 
1687*0Sstevel@tonic-gate 	name=X509_REQ_get_subject_name(req);
1688*0Sstevel@tonic-gate 	for (i=0; i<X509_NAME_entry_count(name); i++)
1689*0Sstevel@tonic-gate 		{
1690*0Sstevel@tonic-gate 		ne= X509_NAME_get_entry(name,i);
1691*0Sstevel@tonic-gate 		str=X509_NAME_ENTRY_get_data(ne);
1692*0Sstevel@tonic-gate 		obj=X509_NAME_ENTRY_get_object(ne);
1693*0Sstevel@tonic-gate 
1694*0Sstevel@tonic-gate 		if (msie_hack)
1695*0Sstevel@tonic-gate 			{
1696*0Sstevel@tonic-gate 			/* assume all type should be strings */
1697*0Sstevel@tonic-gate 			nid=OBJ_obj2nid(ne->object);
1698*0Sstevel@tonic-gate 
1699*0Sstevel@tonic-gate 			if (str->type == V_ASN1_UNIVERSALSTRING)
1700*0Sstevel@tonic-gate 				ASN1_UNIVERSALSTRING_to_string(str);
1701*0Sstevel@tonic-gate 
1702*0Sstevel@tonic-gate 			if ((str->type == V_ASN1_IA5STRING) &&
1703*0Sstevel@tonic-gate 				(nid != NID_pkcs9_emailAddress))
1704*0Sstevel@tonic-gate 				str->type=V_ASN1_T61STRING;
1705*0Sstevel@tonic-gate 
1706*0Sstevel@tonic-gate 			if ((nid == NID_pkcs9_emailAddress) &&
1707*0Sstevel@tonic-gate 				(str->type == V_ASN1_PRINTABLESTRING))
1708*0Sstevel@tonic-gate 				str->type=V_ASN1_IA5STRING;
1709*0Sstevel@tonic-gate 			}
1710*0Sstevel@tonic-gate 
1711*0Sstevel@tonic-gate 		/* If no EMAIL is wanted in the subject */
1712*0Sstevel@tonic-gate 		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1713*0Sstevel@tonic-gate 			continue;
1714*0Sstevel@tonic-gate 
1715*0Sstevel@tonic-gate 		/* check some things */
1716*0Sstevel@tonic-gate 		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1717*0Sstevel@tonic-gate 			(str->type != V_ASN1_IA5STRING))
1718*0Sstevel@tonic-gate 			{
1719*0Sstevel@tonic-gate 			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1720*0Sstevel@tonic-gate 			goto err;
1721*0Sstevel@tonic-gate 			}
1722*0Sstevel@tonic-gate 		if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
1723*0Sstevel@tonic-gate 			{
1724*0Sstevel@tonic-gate 			j=ASN1_PRINTABLE_type(str->data,str->length);
1725*0Sstevel@tonic-gate 			if (	((j == V_ASN1_T61STRING) &&
1726*0Sstevel@tonic-gate 				 (str->type != V_ASN1_T61STRING)) ||
1727*0Sstevel@tonic-gate 				((j == V_ASN1_IA5STRING) &&
1728*0Sstevel@tonic-gate 				 (str->type == V_ASN1_PRINTABLESTRING)))
1729*0Sstevel@tonic-gate 				{
1730*0Sstevel@tonic-gate 				BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1731*0Sstevel@tonic-gate 				goto err;
1732*0Sstevel@tonic-gate 				}
1733*0Sstevel@tonic-gate 			}
1734*0Sstevel@tonic-gate 
1735*0Sstevel@tonic-gate 		if (default_op)
1736*0Sstevel@tonic-gate 			old_entry_print(bio_err, obj, str);
1737*0Sstevel@tonic-gate 		}
1738*0Sstevel@tonic-gate 
1739*0Sstevel@tonic-gate 	/* Ok, now we check the 'policy' stuff. */
1740*0Sstevel@tonic-gate 	if ((subject=X509_NAME_new()) == NULL)
1741*0Sstevel@tonic-gate 		{
1742*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Memory allocation failure\n");
1743*0Sstevel@tonic-gate 		goto err;
1744*0Sstevel@tonic-gate 		}
1745*0Sstevel@tonic-gate 
1746*0Sstevel@tonic-gate 	/* take a copy of the issuer name before we mess with it. */
1747*0Sstevel@tonic-gate 	CAname=X509_NAME_dup(x509->cert_info->subject);
1748*0Sstevel@tonic-gate 	if (CAname == NULL) goto err;
1749*0Sstevel@tonic-gate 	str=str2=NULL;
1750*0Sstevel@tonic-gate 
1751*0Sstevel@tonic-gate 	for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1752*0Sstevel@tonic-gate 		{
1753*0Sstevel@tonic-gate 		cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1754*0Sstevel@tonic-gate 		if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1755*0Sstevel@tonic-gate 			{
1756*0Sstevel@tonic-gate 			BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1757*0Sstevel@tonic-gate 			goto err;
1758*0Sstevel@tonic-gate 			}
1759*0Sstevel@tonic-gate 		obj=OBJ_nid2obj(j);
1760*0Sstevel@tonic-gate 
1761*0Sstevel@tonic-gate 		last= -1;
1762*0Sstevel@tonic-gate 		for (;;)
1763*0Sstevel@tonic-gate 			{
1764*0Sstevel@tonic-gate 			/* lookup the object in the supplied name list */
1765*0Sstevel@tonic-gate 			j=X509_NAME_get_index_by_OBJ(name,obj,last);
1766*0Sstevel@tonic-gate 			if (j < 0)
1767*0Sstevel@tonic-gate 				{
1768*0Sstevel@tonic-gate 				if (last != -1) break;
1769*0Sstevel@tonic-gate 				tne=NULL;
1770*0Sstevel@tonic-gate 				}
1771*0Sstevel@tonic-gate 			else
1772*0Sstevel@tonic-gate 				{
1773*0Sstevel@tonic-gate 				tne=X509_NAME_get_entry(name,j);
1774*0Sstevel@tonic-gate 				}
1775*0Sstevel@tonic-gate 			last=j;
1776*0Sstevel@tonic-gate 
1777*0Sstevel@tonic-gate 			/* depending on the 'policy', decide what to do. */
1778*0Sstevel@tonic-gate 			push=NULL;
1779*0Sstevel@tonic-gate 			if (strcmp(cv->value,"optional") == 0)
1780*0Sstevel@tonic-gate 				{
1781*0Sstevel@tonic-gate 				if (tne != NULL)
1782*0Sstevel@tonic-gate 					push=tne;
1783*0Sstevel@tonic-gate 				}
1784*0Sstevel@tonic-gate 			else if (strcmp(cv->value,"supplied") == 0)
1785*0Sstevel@tonic-gate 				{
1786*0Sstevel@tonic-gate 				if (tne == NULL)
1787*0Sstevel@tonic-gate 					{
1788*0Sstevel@tonic-gate 					BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1789*0Sstevel@tonic-gate 					goto err;
1790*0Sstevel@tonic-gate 					}
1791*0Sstevel@tonic-gate 				else
1792*0Sstevel@tonic-gate 					push=tne;
1793*0Sstevel@tonic-gate 				}
1794*0Sstevel@tonic-gate 			else if (strcmp(cv->value,"match") == 0)
1795*0Sstevel@tonic-gate 				{
1796*0Sstevel@tonic-gate 				int last2;
1797*0Sstevel@tonic-gate 
1798*0Sstevel@tonic-gate 				if (tne == NULL)
1799*0Sstevel@tonic-gate 					{
1800*0Sstevel@tonic-gate 					BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1801*0Sstevel@tonic-gate 					goto err;
1802*0Sstevel@tonic-gate 					}
1803*0Sstevel@tonic-gate 
1804*0Sstevel@tonic-gate 				last2= -1;
1805*0Sstevel@tonic-gate 
1806*0Sstevel@tonic-gate again2:
1807*0Sstevel@tonic-gate 				j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1808*0Sstevel@tonic-gate 				if ((j < 0) && (last2 == -1))
1809*0Sstevel@tonic-gate 					{
1810*0Sstevel@tonic-gate 					BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1811*0Sstevel@tonic-gate 					goto err;
1812*0Sstevel@tonic-gate 					}
1813*0Sstevel@tonic-gate 				if (j >= 0)
1814*0Sstevel@tonic-gate 					{
1815*0Sstevel@tonic-gate 					push=X509_NAME_get_entry(CAname,j);
1816*0Sstevel@tonic-gate 					str=X509_NAME_ENTRY_get_data(tne);
1817*0Sstevel@tonic-gate 					str2=X509_NAME_ENTRY_get_data(push);
1818*0Sstevel@tonic-gate 					last2=j;
1819*0Sstevel@tonic-gate 					if (ASN1_STRING_cmp(str,str2) != 0)
1820*0Sstevel@tonic-gate 						goto again2;
1821*0Sstevel@tonic-gate 					}
1822*0Sstevel@tonic-gate 				if (j < 0)
1823*0Sstevel@tonic-gate 					{
1824*0Sstevel@tonic-gate 					BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data));
1825*0Sstevel@tonic-gate 					goto err;
1826*0Sstevel@tonic-gate 					}
1827*0Sstevel@tonic-gate 				}
1828*0Sstevel@tonic-gate 			else
1829*0Sstevel@tonic-gate 				{
1830*0Sstevel@tonic-gate 				BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1831*0Sstevel@tonic-gate 				goto err;
1832*0Sstevel@tonic-gate 				}
1833*0Sstevel@tonic-gate 
1834*0Sstevel@tonic-gate 			if (push != NULL)
1835*0Sstevel@tonic-gate 				{
1836*0Sstevel@tonic-gate 				if (!X509_NAME_add_entry(subject,push, -1, 0))
1837*0Sstevel@tonic-gate 					{
1838*0Sstevel@tonic-gate 					if (push != NULL)
1839*0Sstevel@tonic-gate 						X509_NAME_ENTRY_free(push);
1840*0Sstevel@tonic-gate 					BIO_printf(bio_err,"Memory allocation failure\n");
1841*0Sstevel@tonic-gate 					goto err;
1842*0Sstevel@tonic-gate 					}
1843*0Sstevel@tonic-gate 				}
1844*0Sstevel@tonic-gate 			if (j < 0) break;
1845*0Sstevel@tonic-gate 			}
1846*0Sstevel@tonic-gate 		}
1847*0Sstevel@tonic-gate 
1848*0Sstevel@tonic-gate 	if (preserve)
1849*0Sstevel@tonic-gate 		{
1850*0Sstevel@tonic-gate 		X509_NAME_free(subject);
1851*0Sstevel@tonic-gate 		/* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1852*0Sstevel@tonic-gate 		subject=X509_NAME_dup(name);
1853*0Sstevel@tonic-gate 		if (subject == NULL) goto err;
1854*0Sstevel@tonic-gate 		}
1855*0Sstevel@tonic-gate 
1856*0Sstevel@tonic-gate 	if (verbose)
1857*0Sstevel@tonic-gate 		BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1858*0Sstevel@tonic-gate 
1859*0Sstevel@tonic-gate 	/* Build the correct Subject if no e-mail is wanted in the subject */
1860*0Sstevel@tonic-gate 	/* and add it later on because of the method extensions are added (altName) */
1861*0Sstevel@tonic-gate 
1862*0Sstevel@tonic-gate 	if (email_dn)
1863*0Sstevel@tonic-gate 		dn_subject = subject;
1864*0Sstevel@tonic-gate 	else
1865*0Sstevel@tonic-gate 		{
1866*0Sstevel@tonic-gate 		X509_NAME_ENTRY *tmpne;
1867*0Sstevel@tonic-gate 		/* Its best to dup the subject DN and then delete any email
1868*0Sstevel@tonic-gate 		 * addresses because this retains its structure.
1869*0Sstevel@tonic-gate 		 */
1870*0Sstevel@tonic-gate 		if (!(dn_subject = X509_NAME_dup(subject)))
1871*0Sstevel@tonic-gate 			{
1872*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Memory allocation failure\n");
1873*0Sstevel@tonic-gate 			goto err;
1874*0Sstevel@tonic-gate 			}
1875*0Sstevel@tonic-gate 		while((i = X509_NAME_get_index_by_NID(dn_subject,
1876*0Sstevel@tonic-gate 					NID_pkcs9_emailAddress, -1)) >= 0)
1877*0Sstevel@tonic-gate 			{
1878*0Sstevel@tonic-gate 			tmpne = X509_NAME_get_entry(dn_subject, i);
1879*0Sstevel@tonic-gate 			X509_NAME_delete_entry(dn_subject, i);
1880*0Sstevel@tonic-gate 			X509_NAME_ENTRY_free(tmpne);
1881*0Sstevel@tonic-gate 			}
1882*0Sstevel@tonic-gate 		}
1883*0Sstevel@tonic-gate 
1884*0Sstevel@tonic-gate 	if (BN_is_zero(serial))
1885*0Sstevel@tonic-gate 		row[DB_serial]=BUF_strdup("00");
1886*0Sstevel@tonic-gate 	else
1887*0Sstevel@tonic-gate 		row[DB_serial]=BN_bn2hex(serial);
1888*0Sstevel@tonic-gate 	if (row[DB_serial] == NULL)
1889*0Sstevel@tonic-gate 		{
1890*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Memory allocation failure\n");
1891*0Sstevel@tonic-gate 		goto err;
1892*0Sstevel@tonic-gate 		}
1893*0Sstevel@tonic-gate 
1894*0Sstevel@tonic-gate 	if (db->attributes.unique_subject)
1895*0Sstevel@tonic-gate 		{
1896*0Sstevel@tonic-gate 		rrow=TXT_DB_get_by_index(db->db,DB_name,row);
1897*0Sstevel@tonic-gate 		if (rrow != NULL)
1898*0Sstevel@tonic-gate 			{
1899*0Sstevel@tonic-gate 			BIO_printf(bio_err,
1900*0Sstevel@tonic-gate 				"ERROR:There is already a certificate for %s\n",
1901*0Sstevel@tonic-gate 				row[DB_name]);
1902*0Sstevel@tonic-gate 			}
1903*0Sstevel@tonic-gate 		}
1904*0Sstevel@tonic-gate 	if (rrow == NULL)
1905*0Sstevel@tonic-gate 		{
1906*0Sstevel@tonic-gate 		rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
1907*0Sstevel@tonic-gate 		if (rrow != NULL)
1908*0Sstevel@tonic-gate 			{
1909*0Sstevel@tonic-gate 			BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1910*0Sstevel@tonic-gate 				row[DB_serial]);
1911*0Sstevel@tonic-gate 			BIO_printf(bio_err,"      check the database/serial_file for corruption\n");
1912*0Sstevel@tonic-gate 			}
1913*0Sstevel@tonic-gate 		}
1914*0Sstevel@tonic-gate 
1915*0Sstevel@tonic-gate 	if (rrow != NULL)
1916*0Sstevel@tonic-gate 		{
1917*0Sstevel@tonic-gate 		BIO_printf(bio_err,
1918*0Sstevel@tonic-gate 			"The matching entry has the following details\n");
1919*0Sstevel@tonic-gate 		if (rrow[DB_type][0] == 'E')
1920*0Sstevel@tonic-gate 			p="Expired";
1921*0Sstevel@tonic-gate 		else if (rrow[DB_type][0] == 'R')
1922*0Sstevel@tonic-gate 			p="Revoked";
1923*0Sstevel@tonic-gate 		else if (rrow[DB_type][0] == 'V')
1924*0Sstevel@tonic-gate 			p="Valid";
1925*0Sstevel@tonic-gate 		else
1926*0Sstevel@tonic-gate 			p="\ninvalid type, Data base error\n";
1927*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Type	  :%s\n",p);;
1928*0Sstevel@tonic-gate 		if (rrow[DB_type][0] == 'R')
1929*0Sstevel@tonic-gate 			{
1930*0Sstevel@tonic-gate 			p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1931*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Was revoked on:%s\n",p);
1932*0Sstevel@tonic-gate 			}
1933*0Sstevel@tonic-gate 		p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1934*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Expires on    :%s\n",p);
1935*0Sstevel@tonic-gate 		p=rrow[DB_serial]; if (p == NULL) p="undef";
1936*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Serial Number :%s\n",p);
1937*0Sstevel@tonic-gate 		p=rrow[DB_file]; if (p == NULL) p="undef";
1938*0Sstevel@tonic-gate 		BIO_printf(bio_err,"File name     :%s\n",p);
1939*0Sstevel@tonic-gate 		p=rrow[DB_name]; if (p == NULL) p="undef";
1940*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Subject Name  :%s\n",p);
1941*0Sstevel@tonic-gate 		ok= -1; /* This is now a 'bad' error. */
1942*0Sstevel@tonic-gate 		goto err;
1943*0Sstevel@tonic-gate 		}
1944*0Sstevel@tonic-gate 
1945*0Sstevel@tonic-gate 	/* We are now totally happy, lets make and sign the certificate */
1946*0Sstevel@tonic-gate 	if (verbose)
1947*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
1948*0Sstevel@tonic-gate 
1949*0Sstevel@tonic-gate 	if ((ret=X509_new()) == NULL) goto err;
1950*0Sstevel@tonic-gate 	ci=ret->cert_info;
1951*0Sstevel@tonic-gate 
1952*0Sstevel@tonic-gate #ifdef X509_V3
1953*0Sstevel@tonic-gate 	/* Make it an X509 v3 certificate. */
1954*0Sstevel@tonic-gate 	if (!X509_set_version(ret,2)) goto err;
1955*0Sstevel@tonic-gate #endif
1956*0Sstevel@tonic-gate 
1957*0Sstevel@tonic-gate 	if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
1958*0Sstevel@tonic-gate 		goto err;
1959*0Sstevel@tonic-gate 	if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1960*0Sstevel@tonic-gate 		goto err;
1961*0Sstevel@tonic-gate 
1962*0Sstevel@tonic-gate 	if (strcmp(startdate,"today") == 0)
1963*0Sstevel@tonic-gate 		X509_gmtime_adj(X509_get_notBefore(ret),0);
1964*0Sstevel@tonic-gate 	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1965*0Sstevel@tonic-gate 
1966*0Sstevel@tonic-gate 	if (enddate == NULL)
1967*0Sstevel@tonic-gate 		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
1968*0Sstevel@tonic-gate 	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1969*0Sstevel@tonic-gate 
1970*0Sstevel@tonic-gate 	if (!X509_set_subject_name(ret,subject)) goto err;
1971*0Sstevel@tonic-gate 
1972*0Sstevel@tonic-gate 	pktmp=X509_REQ_get_pubkey(req);
1973*0Sstevel@tonic-gate 	i = X509_set_pubkey(ret,pktmp);
1974*0Sstevel@tonic-gate 	EVP_PKEY_free(pktmp);
1975*0Sstevel@tonic-gate 	if (!i) goto err;
1976*0Sstevel@tonic-gate 
1977*0Sstevel@tonic-gate 	/* Lets add the extensions, if there are any */
1978*0Sstevel@tonic-gate 	if (ext_sect)
1979*0Sstevel@tonic-gate 		{
1980*0Sstevel@tonic-gate 		X509V3_CTX ctx;
1981*0Sstevel@tonic-gate 		if (ci->version == NULL)
1982*0Sstevel@tonic-gate 			if ((ci->version=ASN1_INTEGER_new()) == NULL)
1983*0Sstevel@tonic-gate 				goto err;
1984*0Sstevel@tonic-gate 		ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
1985*0Sstevel@tonic-gate 
1986*0Sstevel@tonic-gate 		/* Free the current entries if any, there should not
1987*0Sstevel@tonic-gate 		 * be any I believe */
1988*0Sstevel@tonic-gate 		if (ci->extensions != NULL)
1989*0Sstevel@tonic-gate 			sk_X509_EXTENSION_pop_free(ci->extensions,
1990*0Sstevel@tonic-gate 						   X509_EXTENSION_free);
1991*0Sstevel@tonic-gate 
1992*0Sstevel@tonic-gate 		ci->extensions = NULL;
1993*0Sstevel@tonic-gate 
1994*0Sstevel@tonic-gate 		/* Initialize the context structure */
1995*0Sstevel@tonic-gate 		X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
1996*0Sstevel@tonic-gate 
1997*0Sstevel@tonic-gate 		if (extconf)
1998*0Sstevel@tonic-gate 			{
1999*0Sstevel@tonic-gate 			if (verbose)
2000*0Sstevel@tonic-gate 				BIO_printf(bio_err, "Extra configuration file found\n");
2001*0Sstevel@tonic-gate 
2002*0Sstevel@tonic-gate 			/* Use the extconf configuration db LHASH */
2003*0Sstevel@tonic-gate 			X509V3_set_nconf(&ctx, extconf);
2004*0Sstevel@tonic-gate 
2005*0Sstevel@tonic-gate 			/* Test the structure (needed?) */
2006*0Sstevel@tonic-gate 			/* X509V3_set_ctx_test(&ctx); */
2007*0Sstevel@tonic-gate 
2008*0Sstevel@tonic-gate 			/* Adds exts contained in the configuration file */
2009*0Sstevel@tonic-gate 			if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2010*0Sstevel@tonic-gate 				{
2011*0Sstevel@tonic-gate 				BIO_printf(bio_err,
2012*0Sstevel@tonic-gate 				    "ERROR: adding extensions in section %s\n",
2013*0Sstevel@tonic-gate 								ext_sect);
2014*0Sstevel@tonic-gate 				ERR_print_errors(bio_err);
2015*0Sstevel@tonic-gate 				goto err;
2016*0Sstevel@tonic-gate 				}
2017*0Sstevel@tonic-gate 			if (verbose)
2018*0Sstevel@tonic-gate 				BIO_printf(bio_err, "Successfully added extensions from file.\n");
2019*0Sstevel@tonic-gate 			}
2020*0Sstevel@tonic-gate 		else if (ext_sect)
2021*0Sstevel@tonic-gate 			{
2022*0Sstevel@tonic-gate 			/* We found extensions to be set from config file */
2023*0Sstevel@tonic-gate 			X509V3_set_nconf(&ctx, lconf);
2024*0Sstevel@tonic-gate 
2025*0Sstevel@tonic-gate 			if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2026*0Sstevel@tonic-gate 				{
2027*0Sstevel@tonic-gate 				BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2028*0Sstevel@tonic-gate 				ERR_print_errors(bio_err);
2029*0Sstevel@tonic-gate 				goto err;
2030*0Sstevel@tonic-gate 				}
2031*0Sstevel@tonic-gate 
2032*0Sstevel@tonic-gate 			if (verbose)
2033*0Sstevel@tonic-gate 				BIO_printf(bio_err, "Successfully added extensions from config\n");
2034*0Sstevel@tonic-gate 			}
2035*0Sstevel@tonic-gate 		}
2036*0Sstevel@tonic-gate 
2037*0Sstevel@tonic-gate 	/* Copy extensions from request (if any) */
2038*0Sstevel@tonic-gate 
2039*0Sstevel@tonic-gate 	if (!copy_extensions(ret, req, ext_copy))
2040*0Sstevel@tonic-gate 		{
2041*0Sstevel@tonic-gate 		BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2042*0Sstevel@tonic-gate 		ERR_print_errors(bio_err);
2043*0Sstevel@tonic-gate 		goto err;
2044*0Sstevel@tonic-gate 		}
2045*0Sstevel@tonic-gate 
2046*0Sstevel@tonic-gate 	/* Set the right value for the noemailDN option */
2047*0Sstevel@tonic-gate 	if( email_dn == 0 )
2048*0Sstevel@tonic-gate 		{
2049*0Sstevel@tonic-gate 		if (!X509_set_subject_name(ret,dn_subject)) goto err;
2050*0Sstevel@tonic-gate 		}
2051*0Sstevel@tonic-gate 
2052*0Sstevel@tonic-gate 	if (!default_op)
2053*0Sstevel@tonic-gate 		{
2054*0Sstevel@tonic-gate 		BIO_printf(bio_err, "Certificate Details:\n");
2055*0Sstevel@tonic-gate 		/* Never print signature details because signature not present */
2056*0Sstevel@tonic-gate 		certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2057*0Sstevel@tonic-gate 		X509_print_ex(bio_err, ret, nameopt, certopt);
2058*0Sstevel@tonic-gate 		}
2059*0Sstevel@tonic-gate 
2060*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Certificate is to be certified until ");
2061*0Sstevel@tonic-gate 	ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2062*0Sstevel@tonic-gate 	if (days) BIO_printf(bio_err," (%d days)",days);
2063*0Sstevel@tonic-gate 	BIO_printf(bio_err, "\n");
2064*0Sstevel@tonic-gate 
2065*0Sstevel@tonic-gate 	if (!batch)
2066*0Sstevel@tonic-gate 		{
2067*0Sstevel@tonic-gate 
2068*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2069*0Sstevel@tonic-gate 		(void)BIO_flush(bio_err);
2070*0Sstevel@tonic-gate 		buf[0]='\0';
2071*0Sstevel@tonic-gate 		fgets(buf,sizeof(buf)-1,stdin);
2072*0Sstevel@tonic-gate 		if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2073*0Sstevel@tonic-gate 			{
2074*0Sstevel@tonic-gate 			BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2075*0Sstevel@tonic-gate 			ok=0;
2076*0Sstevel@tonic-gate 			goto err;
2077*0Sstevel@tonic-gate 			}
2078*0Sstevel@tonic-gate 		}
2079*0Sstevel@tonic-gate 
2080*0Sstevel@tonic-gate 
2081*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
2082*0Sstevel@tonic-gate 	if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2083*0Sstevel@tonic-gate 	pktmp=X509_get_pubkey(ret);
2084*0Sstevel@tonic-gate 	if (EVP_PKEY_missing_parameters(pktmp) &&
2085*0Sstevel@tonic-gate 		!EVP_PKEY_missing_parameters(pkey))
2086*0Sstevel@tonic-gate 		EVP_PKEY_copy_parameters(pktmp,pkey);
2087*0Sstevel@tonic-gate 	EVP_PKEY_free(pktmp);
2088*0Sstevel@tonic-gate #endif
2089*0Sstevel@tonic-gate 
2090*0Sstevel@tonic-gate 	if (!X509_sign(ret,pkey,dgst))
2091*0Sstevel@tonic-gate 		goto err;
2092*0Sstevel@tonic-gate 
2093*0Sstevel@tonic-gate 	/* We now just add it to the database */
2094*0Sstevel@tonic-gate 	row[DB_type]=(char *)OPENSSL_malloc(2);
2095*0Sstevel@tonic-gate 
2096*0Sstevel@tonic-gate 	tm=X509_get_notAfter(ret);
2097*0Sstevel@tonic-gate 	row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2098*0Sstevel@tonic-gate 	memcpy(row[DB_exp_date],tm->data,tm->length);
2099*0Sstevel@tonic-gate 	row[DB_exp_date][tm->length]='\0';
2100*0Sstevel@tonic-gate 
2101*0Sstevel@tonic-gate 	row[DB_rev_date]=NULL;
2102*0Sstevel@tonic-gate 
2103*0Sstevel@tonic-gate 	/* row[DB_serial] done already */
2104*0Sstevel@tonic-gate 	row[DB_file]=(char *)OPENSSL_malloc(8);
2105*0Sstevel@tonic-gate 	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
2106*0Sstevel@tonic-gate 
2107*0Sstevel@tonic-gate 	if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2108*0Sstevel@tonic-gate 		(row[DB_file] == NULL) || (row[DB_name] == NULL))
2109*0Sstevel@tonic-gate 		{
2110*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Memory allocation failure\n");
2111*0Sstevel@tonic-gate 		goto err;
2112*0Sstevel@tonic-gate 		}
2113*0Sstevel@tonic-gate 	BUF_strlcpy(row[DB_file],"unknown",8);
2114*0Sstevel@tonic-gate 	row[DB_type][0]='V';
2115*0Sstevel@tonic-gate 	row[DB_type][1]='\0';
2116*0Sstevel@tonic-gate 
2117*0Sstevel@tonic-gate 	if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2118*0Sstevel@tonic-gate 		{
2119*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Memory allocation failure\n");
2120*0Sstevel@tonic-gate 		goto err;
2121*0Sstevel@tonic-gate 		}
2122*0Sstevel@tonic-gate 
2123*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2124*0Sstevel@tonic-gate 		{
2125*0Sstevel@tonic-gate 		irow[i]=row[i];
2126*0Sstevel@tonic-gate 		row[i]=NULL;
2127*0Sstevel@tonic-gate 		}
2128*0Sstevel@tonic-gate 	irow[DB_NUMBER]=NULL;
2129*0Sstevel@tonic-gate 
2130*0Sstevel@tonic-gate 	if (!TXT_DB_insert(db->db,irow))
2131*0Sstevel@tonic-gate 		{
2132*0Sstevel@tonic-gate 		BIO_printf(bio_err,"failed to update database\n");
2133*0Sstevel@tonic-gate 		BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2134*0Sstevel@tonic-gate 		goto err;
2135*0Sstevel@tonic-gate 		}
2136*0Sstevel@tonic-gate 	ok=1;
2137*0Sstevel@tonic-gate err:
2138*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2139*0Sstevel@tonic-gate 		if (row[i] != NULL) OPENSSL_free(row[i]);
2140*0Sstevel@tonic-gate 
2141*0Sstevel@tonic-gate 	if (CAname != NULL)
2142*0Sstevel@tonic-gate 		X509_NAME_free(CAname);
2143*0Sstevel@tonic-gate 	if (subject != NULL)
2144*0Sstevel@tonic-gate 		X509_NAME_free(subject);
2145*0Sstevel@tonic-gate 	if ((dn_subject != NULL) && !email_dn)
2146*0Sstevel@tonic-gate 		X509_NAME_free(dn_subject);
2147*0Sstevel@tonic-gate 	if (tmptm != NULL)
2148*0Sstevel@tonic-gate 		ASN1_UTCTIME_free(tmptm);
2149*0Sstevel@tonic-gate 	if (ok <= 0)
2150*0Sstevel@tonic-gate 		{
2151*0Sstevel@tonic-gate 		if (ret != NULL) X509_free(ret);
2152*0Sstevel@tonic-gate 		ret=NULL;
2153*0Sstevel@tonic-gate 		}
2154*0Sstevel@tonic-gate 	else
2155*0Sstevel@tonic-gate 		*xret=ret;
2156*0Sstevel@tonic-gate 	return(ok);
2157*0Sstevel@tonic-gate 	}
2158*0Sstevel@tonic-gate 
2159*0Sstevel@tonic-gate static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2160*0Sstevel@tonic-gate 	{
2161*0Sstevel@tonic-gate 
2162*0Sstevel@tonic-gate 	if (output_der)
2163*0Sstevel@tonic-gate 		{
2164*0Sstevel@tonic-gate 		(void)i2d_X509_bio(bp,x);
2165*0Sstevel@tonic-gate 		return;
2166*0Sstevel@tonic-gate 		}
2167*0Sstevel@tonic-gate #if 0
2168*0Sstevel@tonic-gate 	/* ??? Not needed since X509_print prints all this stuff anyway */
2169*0Sstevel@tonic-gate 	f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2170*0Sstevel@tonic-gate 	BIO_printf(bp,"issuer :%s\n",f);
2171*0Sstevel@tonic-gate 
2172*0Sstevel@tonic-gate 	f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2173*0Sstevel@tonic-gate 	BIO_printf(bp,"subject:%s\n",f);
2174*0Sstevel@tonic-gate 
2175*0Sstevel@tonic-gate 	BIO_puts(bp,"serial :");
2176*0Sstevel@tonic-gate 	i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2177*0Sstevel@tonic-gate 	BIO_puts(bp,"\n\n");
2178*0Sstevel@tonic-gate #endif
2179*0Sstevel@tonic-gate 	if (!notext)X509_print(bp,x);
2180*0Sstevel@tonic-gate 	PEM_write_bio_X509(bp,x);
2181*0Sstevel@tonic-gate 	}
2182*0Sstevel@tonic-gate 
2183*0Sstevel@tonic-gate static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2184*0Sstevel@tonic-gate 	     const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2185*0Sstevel@tonic-gate 	     BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
2186*0Sstevel@tonic-gate 	     long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2187*0Sstevel@tonic-gate 	     unsigned long nameopt, int default_op, int ext_copy)
2188*0Sstevel@tonic-gate 	{
2189*0Sstevel@tonic-gate 	STACK_OF(CONF_VALUE) *sk=NULL;
2190*0Sstevel@tonic-gate 	LHASH *parms=NULL;
2191*0Sstevel@tonic-gate 	X509_REQ *req=NULL;
2192*0Sstevel@tonic-gate 	CONF_VALUE *cv=NULL;
2193*0Sstevel@tonic-gate 	NETSCAPE_SPKI *spki = NULL;
2194*0Sstevel@tonic-gate 	X509_REQ_INFO *ri;
2195*0Sstevel@tonic-gate 	char *type,*buf;
2196*0Sstevel@tonic-gate 	EVP_PKEY *pktmp=NULL;
2197*0Sstevel@tonic-gate 	X509_NAME *n=NULL;
2198*0Sstevel@tonic-gate 	X509_NAME_ENTRY *ne=NULL;
2199*0Sstevel@tonic-gate 	int ok= -1,i,j;
2200*0Sstevel@tonic-gate 	long errline;
2201*0Sstevel@tonic-gate 	int nid;
2202*0Sstevel@tonic-gate 
2203*0Sstevel@tonic-gate 	/*
2204*0Sstevel@tonic-gate 	 * Load input file into a hash table.  (This is just an easy
2205*0Sstevel@tonic-gate 	 * way to read and parse the file, then put it into a convenient
2206*0Sstevel@tonic-gate 	 * STACK format).
2207*0Sstevel@tonic-gate 	 */
2208*0Sstevel@tonic-gate 	parms=CONF_load(NULL,infile,&errline);
2209*0Sstevel@tonic-gate 	if (parms == NULL)
2210*0Sstevel@tonic-gate 		{
2211*0Sstevel@tonic-gate 		BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2212*0Sstevel@tonic-gate 		ERR_print_errors(bio_err);
2213*0Sstevel@tonic-gate 		goto err;
2214*0Sstevel@tonic-gate 		}
2215*0Sstevel@tonic-gate 
2216*0Sstevel@tonic-gate 	sk=CONF_get_section(parms, "default");
2217*0Sstevel@tonic-gate 	if (sk_CONF_VALUE_num(sk) == 0)
2218*0Sstevel@tonic-gate 		{
2219*0Sstevel@tonic-gate 		BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2220*0Sstevel@tonic-gate 		CONF_free(parms);
2221*0Sstevel@tonic-gate 		goto err;
2222*0Sstevel@tonic-gate 		}
2223*0Sstevel@tonic-gate 
2224*0Sstevel@tonic-gate 	/*
2225*0Sstevel@tonic-gate 	 * Now create a dummy X509 request structure.  We don't actually
2226*0Sstevel@tonic-gate 	 * have an X509 request, but we have many of the components
2227*0Sstevel@tonic-gate 	 * (a public key, various DN components).  The idea is that we
2228*0Sstevel@tonic-gate 	 * put these components into the right X509 request structure
2229*0Sstevel@tonic-gate 	 * and we can use the same code as if you had a real X509 request.
2230*0Sstevel@tonic-gate 	 */
2231*0Sstevel@tonic-gate 	req=X509_REQ_new();
2232*0Sstevel@tonic-gate 	if (req == NULL)
2233*0Sstevel@tonic-gate 		{
2234*0Sstevel@tonic-gate 		ERR_print_errors(bio_err);
2235*0Sstevel@tonic-gate 		goto err;
2236*0Sstevel@tonic-gate 		}
2237*0Sstevel@tonic-gate 
2238*0Sstevel@tonic-gate 	/*
2239*0Sstevel@tonic-gate 	 * Build up the subject name set.
2240*0Sstevel@tonic-gate 	 */
2241*0Sstevel@tonic-gate 	ri=req->req_info;
2242*0Sstevel@tonic-gate 	n = ri->subject;
2243*0Sstevel@tonic-gate 
2244*0Sstevel@tonic-gate 	for (i = 0; ; i++)
2245*0Sstevel@tonic-gate 		{
2246*0Sstevel@tonic-gate 		if (sk_CONF_VALUE_num(sk) <= i) break;
2247*0Sstevel@tonic-gate 
2248*0Sstevel@tonic-gate 		cv=sk_CONF_VALUE_value(sk,i);
2249*0Sstevel@tonic-gate 		type=cv->name;
2250*0Sstevel@tonic-gate 		/* Skip past any leading X. X: X, etc to allow for
2251*0Sstevel@tonic-gate 		 * multiple instances
2252*0Sstevel@tonic-gate 		 */
2253*0Sstevel@tonic-gate 		for (buf = cv->name; *buf ; buf++)
2254*0Sstevel@tonic-gate 			if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2255*0Sstevel@tonic-gate 				{
2256*0Sstevel@tonic-gate 				buf++;
2257*0Sstevel@tonic-gate 				if (*buf) type = buf;
2258*0Sstevel@tonic-gate 				break;
2259*0Sstevel@tonic-gate 				}
2260*0Sstevel@tonic-gate 
2261*0Sstevel@tonic-gate 		buf=cv->value;
2262*0Sstevel@tonic-gate 		if ((nid=OBJ_txt2nid(type)) == NID_undef)
2263*0Sstevel@tonic-gate 			{
2264*0Sstevel@tonic-gate 			if (strcmp(type, "SPKAC") == 0)
2265*0Sstevel@tonic-gate 				{
2266*0Sstevel@tonic-gate 				spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2267*0Sstevel@tonic-gate 				if (spki == NULL)
2268*0Sstevel@tonic-gate 					{
2269*0Sstevel@tonic-gate 					BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2270*0Sstevel@tonic-gate 					ERR_print_errors(bio_err);
2271*0Sstevel@tonic-gate 					goto err;
2272*0Sstevel@tonic-gate 					}
2273*0Sstevel@tonic-gate 				}
2274*0Sstevel@tonic-gate 			continue;
2275*0Sstevel@tonic-gate 			}
2276*0Sstevel@tonic-gate 
2277*0Sstevel@tonic-gate 		/*
2278*0Sstevel@tonic-gate 		if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
2279*0Sstevel@tonic-gate 			continue;
2280*0Sstevel@tonic-gate 		*/
2281*0Sstevel@tonic-gate 
2282*0Sstevel@tonic-gate 		j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2283*0Sstevel@tonic-gate 		if (fix_data(nid, &j) == 0)
2284*0Sstevel@tonic-gate 			{
2285*0Sstevel@tonic-gate 			BIO_printf(bio_err,
2286*0Sstevel@tonic-gate 				"invalid characters in string %s\n",buf);
2287*0Sstevel@tonic-gate 			goto err;
2288*0Sstevel@tonic-gate 			}
2289*0Sstevel@tonic-gate 
2290*0Sstevel@tonic-gate 		if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2291*0Sstevel@tonic-gate 			(unsigned char *)buf,
2292*0Sstevel@tonic-gate 			strlen(buf))) == NULL)
2293*0Sstevel@tonic-gate 			goto err;
2294*0Sstevel@tonic-gate 
2295*0Sstevel@tonic-gate 		if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2296*0Sstevel@tonic-gate 		}
2297*0Sstevel@tonic-gate 	if (spki == NULL)
2298*0Sstevel@tonic-gate 		{
2299*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2300*0Sstevel@tonic-gate 			infile);
2301*0Sstevel@tonic-gate 		goto err;
2302*0Sstevel@tonic-gate 		}
2303*0Sstevel@tonic-gate 
2304*0Sstevel@tonic-gate 	/*
2305*0Sstevel@tonic-gate 	 * Now extract the key from the SPKI structure.
2306*0Sstevel@tonic-gate 	 */
2307*0Sstevel@tonic-gate 
2308*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2309*0Sstevel@tonic-gate 
2310*0Sstevel@tonic-gate 	if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2311*0Sstevel@tonic-gate 		{
2312*0Sstevel@tonic-gate 		BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2313*0Sstevel@tonic-gate 		goto err;
2314*0Sstevel@tonic-gate 		}
2315*0Sstevel@tonic-gate 
2316*0Sstevel@tonic-gate 	j = NETSCAPE_SPKI_verify(spki, pktmp);
2317*0Sstevel@tonic-gate 	if (j <= 0)
2318*0Sstevel@tonic-gate 		{
2319*0Sstevel@tonic-gate 		BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2320*0Sstevel@tonic-gate 		goto err;
2321*0Sstevel@tonic-gate 		}
2322*0Sstevel@tonic-gate 	BIO_printf(bio_err,"Signature ok\n");
2323*0Sstevel@tonic-gate 
2324*0Sstevel@tonic-gate 	X509_REQ_set_pubkey(req,pktmp);
2325*0Sstevel@tonic-gate 	EVP_PKEY_free(pktmp);
2326*0Sstevel@tonic-gate 	ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
2327*0Sstevel@tonic-gate 		   days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2328*0Sstevel@tonic-gate 			ext_copy);
2329*0Sstevel@tonic-gate err:
2330*0Sstevel@tonic-gate 	if (req != NULL) X509_REQ_free(req);
2331*0Sstevel@tonic-gate 	if (parms != NULL) CONF_free(parms);
2332*0Sstevel@tonic-gate 	if (spki != NULL) NETSCAPE_SPKI_free(spki);
2333*0Sstevel@tonic-gate 	if (ne != NULL) X509_NAME_ENTRY_free(ne);
2334*0Sstevel@tonic-gate 
2335*0Sstevel@tonic-gate 	return(ok);
2336*0Sstevel@tonic-gate 	}
2337*0Sstevel@tonic-gate 
2338*0Sstevel@tonic-gate static int fix_data(int nid, int *type)
2339*0Sstevel@tonic-gate 	{
2340*0Sstevel@tonic-gate 	if (nid == NID_pkcs9_emailAddress)
2341*0Sstevel@tonic-gate 		*type=V_ASN1_IA5STRING;
2342*0Sstevel@tonic-gate 	if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2343*0Sstevel@tonic-gate 		*type=V_ASN1_T61STRING;
2344*0Sstevel@tonic-gate 	if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2345*0Sstevel@tonic-gate 		*type=V_ASN1_T61STRING;
2346*0Sstevel@tonic-gate 	if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2347*0Sstevel@tonic-gate 		return(0);
2348*0Sstevel@tonic-gate 	if (nid == NID_pkcs9_unstructuredName)
2349*0Sstevel@tonic-gate 		*type=V_ASN1_IA5STRING;
2350*0Sstevel@tonic-gate 	return(1);
2351*0Sstevel@tonic-gate 	}
2352*0Sstevel@tonic-gate 
2353*0Sstevel@tonic-gate static int check_time_format(char *str)
2354*0Sstevel@tonic-gate 	{
2355*0Sstevel@tonic-gate 	ASN1_UTCTIME tm;
2356*0Sstevel@tonic-gate 
2357*0Sstevel@tonic-gate 	tm.data=(unsigned char *)str;
2358*0Sstevel@tonic-gate 	tm.length=strlen(str);
2359*0Sstevel@tonic-gate 	tm.type=V_ASN1_UTCTIME;
2360*0Sstevel@tonic-gate 	return(ASN1_UTCTIME_check(&tm));
2361*0Sstevel@tonic-gate 	}
2362*0Sstevel@tonic-gate 
2363*0Sstevel@tonic-gate static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2364*0Sstevel@tonic-gate 	{
2365*0Sstevel@tonic-gate 	ASN1_UTCTIME *tm=NULL;
2366*0Sstevel@tonic-gate 	char *row[DB_NUMBER],**rrow,**irow;
2367*0Sstevel@tonic-gate 	char *rev_str = NULL;
2368*0Sstevel@tonic-gate 	BIGNUM *bn = NULL;
2369*0Sstevel@tonic-gate 	int ok=-1,i;
2370*0Sstevel@tonic-gate 
2371*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2372*0Sstevel@tonic-gate 		row[i]=NULL;
2373*0Sstevel@tonic-gate 	row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2374*0Sstevel@tonic-gate 	bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2375*0Sstevel@tonic-gate 	if (BN_is_zero(bn))
2376*0Sstevel@tonic-gate 		row[DB_serial]=BUF_strdup("00");
2377*0Sstevel@tonic-gate 	else
2378*0Sstevel@tonic-gate 		row[DB_serial]=BN_bn2hex(bn);
2379*0Sstevel@tonic-gate 	BN_free(bn);
2380*0Sstevel@tonic-gate 	if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2381*0Sstevel@tonic-gate 		{
2382*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Memory allocation failure\n");
2383*0Sstevel@tonic-gate 		goto err;
2384*0Sstevel@tonic-gate 		}
2385*0Sstevel@tonic-gate 	/* We have to lookup by serial number because name lookup
2386*0Sstevel@tonic-gate 	 * skips revoked certs
2387*0Sstevel@tonic-gate  	 */
2388*0Sstevel@tonic-gate 	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2389*0Sstevel@tonic-gate 	if (rrow == NULL)
2390*0Sstevel@tonic-gate 		{
2391*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
2392*0Sstevel@tonic-gate 
2393*0Sstevel@tonic-gate 		/* We now just add it to the database */
2394*0Sstevel@tonic-gate 		row[DB_type]=(char *)OPENSSL_malloc(2);
2395*0Sstevel@tonic-gate 
2396*0Sstevel@tonic-gate 		tm=X509_get_notAfter(x509);
2397*0Sstevel@tonic-gate 		row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2398*0Sstevel@tonic-gate 		memcpy(row[DB_exp_date],tm->data,tm->length);
2399*0Sstevel@tonic-gate 		row[DB_exp_date][tm->length]='\0';
2400*0Sstevel@tonic-gate 
2401*0Sstevel@tonic-gate 		row[DB_rev_date]=NULL;
2402*0Sstevel@tonic-gate 
2403*0Sstevel@tonic-gate 		/* row[DB_serial] done already */
2404*0Sstevel@tonic-gate 		row[DB_file]=(char *)OPENSSL_malloc(8);
2405*0Sstevel@tonic-gate 
2406*0Sstevel@tonic-gate 		/* row[DB_name] done already */
2407*0Sstevel@tonic-gate 
2408*0Sstevel@tonic-gate 		if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2409*0Sstevel@tonic-gate 			(row[DB_file] == NULL))
2410*0Sstevel@tonic-gate 			{
2411*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Memory allocation failure\n");
2412*0Sstevel@tonic-gate 			goto err;
2413*0Sstevel@tonic-gate 			}
2414*0Sstevel@tonic-gate 		BUF_strlcpy(row[DB_file],"unknown",8);
2415*0Sstevel@tonic-gate 		row[DB_type][0]='V';
2416*0Sstevel@tonic-gate 		row[DB_type][1]='\0';
2417*0Sstevel@tonic-gate 
2418*0Sstevel@tonic-gate 		if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2419*0Sstevel@tonic-gate 			{
2420*0Sstevel@tonic-gate 			BIO_printf(bio_err,"Memory allocation failure\n");
2421*0Sstevel@tonic-gate 			goto err;
2422*0Sstevel@tonic-gate 			}
2423*0Sstevel@tonic-gate 
2424*0Sstevel@tonic-gate 		for (i=0; i<DB_NUMBER; i++)
2425*0Sstevel@tonic-gate 			{
2426*0Sstevel@tonic-gate 			irow[i]=row[i];
2427*0Sstevel@tonic-gate 			row[i]=NULL;
2428*0Sstevel@tonic-gate 			}
2429*0Sstevel@tonic-gate 		irow[DB_NUMBER]=NULL;
2430*0Sstevel@tonic-gate 
2431*0Sstevel@tonic-gate 		if (!TXT_DB_insert(db->db,irow))
2432*0Sstevel@tonic-gate 			{
2433*0Sstevel@tonic-gate 			BIO_printf(bio_err,"failed to update database\n");
2434*0Sstevel@tonic-gate 			BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2435*0Sstevel@tonic-gate 			goto err;
2436*0Sstevel@tonic-gate 			}
2437*0Sstevel@tonic-gate 
2438*0Sstevel@tonic-gate 		/* Revoke Certificate */
2439*0Sstevel@tonic-gate 		ok = do_revoke(x509,db, type, value);
2440*0Sstevel@tonic-gate 
2441*0Sstevel@tonic-gate 		goto err;
2442*0Sstevel@tonic-gate 
2443*0Sstevel@tonic-gate 		}
2444*0Sstevel@tonic-gate 	else if (index_name_cmp((const char **)row,(const char **)rrow))
2445*0Sstevel@tonic-gate 		{
2446*0Sstevel@tonic-gate 		BIO_printf(bio_err,"ERROR:name does not match %s\n",
2447*0Sstevel@tonic-gate 			   row[DB_name]);
2448*0Sstevel@tonic-gate 		goto err;
2449*0Sstevel@tonic-gate 		}
2450*0Sstevel@tonic-gate 	else if (rrow[DB_type][0]=='R')
2451*0Sstevel@tonic-gate 		{
2452*0Sstevel@tonic-gate 		BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2453*0Sstevel@tonic-gate 			   row[DB_serial]);
2454*0Sstevel@tonic-gate 		goto err;
2455*0Sstevel@tonic-gate 		}
2456*0Sstevel@tonic-gate 	else
2457*0Sstevel@tonic-gate 		{
2458*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2459*0Sstevel@tonic-gate 		rev_str = make_revocation_str(type, value);
2460*0Sstevel@tonic-gate 		if (!rev_str)
2461*0Sstevel@tonic-gate 			{
2462*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Error in revocation arguments\n");
2463*0Sstevel@tonic-gate 			goto err;
2464*0Sstevel@tonic-gate 			}
2465*0Sstevel@tonic-gate 		rrow[DB_type][0]='R';
2466*0Sstevel@tonic-gate 		rrow[DB_type][1]='\0';
2467*0Sstevel@tonic-gate 		rrow[DB_rev_date] = rev_str;
2468*0Sstevel@tonic-gate 		}
2469*0Sstevel@tonic-gate 	ok=1;
2470*0Sstevel@tonic-gate err:
2471*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2472*0Sstevel@tonic-gate 		{
2473*0Sstevel@tonic-gate 		if (row[i] != NULL)
2474*0Sstevel@tonic-gate 			OPENSSL_free(row[i]);
2475*0Sstevel@tonic-gate 		}
2476*0Sstevel@tonic-gate 	return(ok);
2477*0Sstevel@tonic-gate 	}
2478*0Sstevel@tonic-gate 
2479*0Sstevel@tonic-gate static int get_certificate_status(const char *serial, CA_DB *db)
2480*0Sstevel@tonic-gate 	{
2481*0Sstevel@tonic-gate 	char *row[DB_NUMBER],**rrow;
2482*0Sstevel@tonic-gate 	int ok=-1,i;
2483*0Sstevel@tonic-gate 
2484*0Sstevel@tonic-gate 	/* Free Resources */
2485*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2486*0Sstevel@tonic-gate 		row[i]=NULL;
2487*0Sstevel@tonic-gate 
2488*0Sstevel@tonic-gate 	/* Malloc needed char spaces */
2489*0Sstevel@tonic-gate 	row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2490*0Sstevel@tonic-gate 	if (row[DB_serial] == NULL)
2491*0Sstevel@tonic-gate 		{
2492*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Malloc failure\n");
2493*0Sstevel@tonic-gate 		goto err;
2494*0Sstevel@tonic-gate 		}
2495*0Sstevel@tonic-gate 
2496*0Sstevel@tonic-gate 	if (strlen(serial) % 2)
2497*0Sstevel@tonic-gate 		{
2498*0Sstevel@tonic-gate 		/* Set the first char to 0 */;
2499*0Sstevel@tonic-gate 		row[DB_serial][0]='0';
2500*0Sstevel@tonic-gate 
2501*0Sstevel@tonic-gate 		/* Copy String from serial to row[DB_serial] */
2502*0Sstevel@tonic-gate 		memcpy(row[DB_serial]+1, serial, strlen(serial));
2503*0Sstevel@tonic-gate 		row[DB_serial][strlen(serial)+1]='\0';
2504*0Sstevel@tonic-gate 		}
2505*0Sstevel@tonic-gate 	else
2506*0Sstevel@tonic-gate 		{
2507*0Sstevel@tonic-gate 		/* Copy String from serial to row[DB_serial] */
2508*0Sstevel@tonic-gate 		memcpy(row[DB_serial], serial, strlen(serial));
2509*0Sstevel@tonic-gate 		row[DB_serial][strlen(serial)]='\0';
2510*0Sstevel@tonic-gate 		}
2511*0Sstevel@tonic-gate 
2512*0Sstevel@tonic-gate 	/* Make it Upper Case */
2513*0Sstevel@tonic-gate 	for (i=0; row[DB_serial][i] != '\0'; i++)
2514*0Sstevel@tonic-gate 		row[DB_serial][i] = toupper(row[DB_serial][i]);
2515*0Sstevel@tonic-gate 
2516*0Sstevel@tonic-gate 
2517*0Sstevel@tonic-gate 	ok=1;
2518*0Sstevel@tonic-gate 
2519*0Sstevel@tonic-gate 	/* Search for the certificate */
2520*0Sstevel@tonic-gate 	rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2521*0Sstevel@tonic-gate 	if (rrow == NULL)
2522*0Sstevel@tonic-gate 		{
2523*0Sstevel@tonic-gate 		BIO_printf(bio_err,"Serial %s not present in db.\n",
2524*0Sstevel@tonic-gate 				 row[DB_serial]);
2525*0Sstevel@tonic-gate 		ok=-1;
2526*0Sstevel@tonic-gate 		goto err;
2527*0Sstevel@tonic-gate 		}
2528*0Sstevel@tonic-gate 	else if (rrow[DB_type][0]=='V')
2529*0Sstevel@tonic-gate 		{
2530*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%s=Valid (%c)\n",
2531*0Sstevel@tonic-gate 			row[DB_serial], rrow[DB_type][0]);
2532*0Sstevel@tonic-gate 		goto err;
2533*0Sstevel@tonic-gate 		}
2534*0Sstevel@tonic-gate 	else if (rrow[DB_type][0]=='R')
2535*0Sstevel@tonic-gate 		{
2536*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%s=Revoked (%c)\n",
2537*0Sstevel@tonic-gate 			row[DB_serial], rrow[DB_type][0]);
2538*0Sstevel@tonic-gate 		goto err;
2539*0Sstevel@tonic-gate 		}
2540*0Sstevel@tonic-gate 	else if (rrow[DB_type][0]=='E')
2541*0Sstevel@tonic-gate 		{
2542*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%s=Expired (%c)\n",
2543*0Sstevel@tonic-gate 			row[DB_serial], rrow[DB_type][0]);
2544*0Sstevel@tonic-gate 		goto err;
2545*0Sstevel@tonic-gate 		}
2546*0Sstevel@tonic-gate 	else if (rrow[DB_type][0]=='S')
2547*0Sstevel@tonic-gate 		{
2548*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%s=Suspended (%c)\n",
2549*0Sstevel@tonic-gate 			row[DB_serial], rrow[DB_type][0]);
2550*0Sstevel@tonic-gate 		goto err;
2551*0Sstevel@tonic-gate 		}
2552*0Sstevel@tonic-gate 	else
2553*0Sstevel@tonic-gate 		{
2554*0Sstevel@tonic-gate 		BIO_printf(bio_err,"%s=Unknown (%c).\n",
2555*0Sstevel@tonic-gate 			row[DB_serial], rrow[DB_type][0]);
2556*0Sstevel@tonic-gate 		ok=-1;
2557*0Sstevel@tonic-gate 		}
2558*0Sstevel@tonic-gate err:
2559*0Sstevel@tonic-gate 	for (i=0; i<DB_NUMBER; i++)
2560*0Sstevel@tonic-gate 		{
2561*0Sstevel@tonic-gate 		if (row[i] != NULL)
2562*0Sstevel@tonic-gate 			OPENSSL_free(row[i]);
2563*0Sstevel@tonic-gate 		}
2564*0Sstevel@tonic-gate 	return(ok);
2565*0Sstevel@tonic-gate 	}
2566*0Sstevel@tonic-gate 
2567*0Sstevel@tonic-gate static int do_updatedb (CA_DB *db)
2568*0Sstevel@tonic-gate 	{
2569*0Sstevel@tonic-gate 	ASN1_UTCTIME	*a_tm = NULL;
2570*0Sstevel@tonic-gate 	int i, cnt = 0;
2571*0Sstevel@tonic-gate 	int db_y2k, a_y2k;  /* flags = 1 if y >= 2000 */
2572*0Sstevel@tonic-gate 	char **rrow, *a_tm_s;
2573*0Sstevel@tonic-gate 
2574*0Sstevel@tonic-gate 	a_tm = ASN1_UTCTIME_new();
2575*0Sstevel@tonic-gate 
2576*0Sstevel@tonic-gate 	/* get actual time and make a string */
2577*0Sstevel@tonic-gate 	a_tm = X509_gmtime_adj(a_tm, 0);
2578*0Sstevel@tonic-gate 	a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2579*0Sstevel@tonic-gate 	if (a_tm_s == NULL)
2580*0Sstevel@tonic-gate 		{
2581*0Sstevel@tonic-gate 		cnt = -1;
2582*0Sstevel@tonic-gate 		goto err;
2583*0Sstevel@tonic-gate 		}
2584*0Sstevel@tonic-gate 
2585*0Sstevel@tonic-gate 	memcpy(a_tm_s, a_tm->data, a_tm->length);
2586*0Sstevel@tonic-gate 	a_tm_s[a_tm->length] = '\0';
2587*0Sstevel@tonic-gate 
2588*0Sstevel@tonic-gate 	if (strncmp(a_tm_s, "49", 2) <= 0)
2589*0Sstevel@tonic-gate 		a_y2k = 1;
2590*0Sstevel@tonic-gate 	else
2591*0Sstevel@tonic-gate 		a_y2k = 0;
2592*0Sstevel@tonic-gate 
2593*0Sstevel@tonic-gate 	for (i = 0; i < sk_num(db->db->data); i++)
2594*0Sstevel@tonic-gate 		{
2595*0Sstevel@tonic-gate 		rrow = (char **) sk_value(db->db->data, i);
2596*0Sstevel@tonic-gate 
2597*0Sstevel@tonic-gate 		if (rrow[DB_type][0] == 'V')
2598*0Sstevel@tonic-gate 		 	{
2599*0Sstevel@tonic-gate 			/* ignore entries that are not valid */
2600*0Sstevel@tonic-gate 			if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2601*0Sstevel@tonic-gate 				db_y2k = 1;
2602*0Sstevel@tonic-gate 			else
2603*0Sstevel@tonic-gate 				db_y2k = 0;
2604*0Sstevel@tonic-gate 
2605*0Sstevel@tonic-gate 			if (db_y2k == a_y2k)
2606*0Sstevel@tonic-gate 				{
2607*0Sstevel@tonic-gate 				/* all on the same y2k side */
2608*0Sstevel@tonic-gate 				if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2609*0Sstevel@tonic-gate 				       	{
2610*0Sstevel@tonic-gate 				       	rrow[DB_type][0]  = 'E';
2611*0Sstevel@tonic-gate 				       	rrow[DB_type][1]  = '\0';
2612*0Sstevel@tonic-gate 	  				cnt++;
2613*0Sstevel@tonic-gate 
2614*0Sstevel@tonic-gate 					BIO_printf(bio_err, "%s=Expired\n",
2615*0Sstevel@tonic-gate 							rrow[DB_serial]);
2616*0Sstevel@tonic-gate 					}
2617*0Sstevel@tonic-gate 				}
2618*0Sstevel@tonic-gate 			else if (db_y2k < a_y2k)
2619*0Sstevel@tonic-gate 				{
2620*0Sstevel@tonic-gate 		  		rrow[DB_type][0]  = 'E';
2621*0Sstevel@tonic-gate 		  		rrow[DB_type][1]  = '\0';
2622*0Sstevel@tonic-gate 	  			cnt++;
2623*0Sstevel@tonic-gate 
2624*0Sstevel@tonic-gate 				BIO_printf(bio_err, "%s=Expired\n",
2625*0Sstevel@tonic-gate 							rrow[DB_serial]);
2626*0Sstevel@tonic-gate 				}
2627*0Sstevel@tonic-gate 
2628*0Sstevel@tonic-gate 			}
2629*0Sstevel@tonic-gate     		}
2630*0Sstevel@tonic-gate 
2631*0Sstevel@tonic-gate err:
2632*0Sstevel@tonic-gate 
2633*0Sstevel@tonic-gate 	ASN1_UTCTIME_free(a_tm);
2634*0Sstevel@tonic-gate 	OPENSSL_free(a_tm_s);
2635*0Sstevel@tonic-gate 
2636*0Sstevel@tonic-gate 	return (cnt);
2637*0Sstevel@tonic-gate 	}
2638*0Sstevel@tonic-gate 
2639*0Sstevel@tonic-gate static char *crl_reasons[] = {
2640*0Sstevel@tonic-gate 	/* CRL reason strings */
2641*0Sstevel@tonic-gate 	"unspecified",
2642*0Sstevel@tonic-gate 	"keyCompromise",
2643*0Sstevel@tonic-gate 	"CACompromise",
2644*0Sstevel@tonic-gate 	"affiliationChanged",
2645*0Sstevel@tonic-gate 	"superseded",
2646*0Sstevel@tonic-gate 	"cessationOfOperation",
2647*0Sstevel@tonic-gate 	"certificateHold",
2648*0Sstevel@tonic-gate 	"removeFromCRL",
2649*0Sstevel@tonic-gate 	/* Additional pseudo reasons */
2650*0Sstevel@tonic-gate 	"holdInstruction",
2651*0Sstevel@tonic-gate 	"keyTime",
2652*0Sstevel@tonic-gate 	"CAkeyTime"
2653*0Sstevel@tonic-gate };
2654*0Sstevel@tonic-gate 
2655*0Sstevel@tonic-gate #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2656*0Sstevel@tonic-gate 
2657*0Sstevel@tonic-gate /* Given revocation information convert to a DB string.
2658*0Sstevel@tonic-gate  * The format of the string is:
2659*0Sstevel@tonic-gate  * revtime[,reason,extra]. Where 'revtime' is the
2660*0Sstevel@tonic-gate  * revocation time (the current time). 'reason' is the
2661*0Sstevel@tonic-gate  * optional CRL reason and 'extra' is any additional
2662*0Sstevel@tonic-gate  * argument
2663*0Sstevel@tonic-gate  */
2664*0Sstevel@tonic-gate 
2665*0Sstevel@tonic-gate char *make_revocation_str(int rev_type, char *rev_arg)
2666*0Sstevel@tonic-gate 	{
2667*0Sstevel@tonic-gate 	char *reason = NULL, *other = NULL, *str;
2668*0Sstevel@tonic-gate 	ASN1_OBJECT *otmp;
2669*0Sstevel@tonic-gate 	ASN1_UTCTIME *revtm = NULL;
2670*0Sstevel@tonic-gate 	int i;
2671*0Sstevel@tonic-gate 	switch (rev_type)
2672*0Sstevel@tonic-gate 		{
2673*0Sstevel@tonic-gate 	case REV_NONE:
2674*0Sstevel@tonic-gate 		break;
2675*0Sstevel@tonic-gate 
2676*0Sstevel@tonic-gate 	case REV_CRL_REASON:
2677*0Sstevel@tonic-gate 		for (i = 0; i < 8; i++)
2678*0Sstevel@tonic-gate 			{
2679*0Sstevel@tonic-gate 			if (!strcasecmp(rev_arg, crl_reasons[i]))
2680*0Sstevel@tonic-gate 				{
2681*0Sstevel@tonic-gate 				reason = crl_reasons[i];
2682*0Sstevel@tonic-gate 				break;
2683*0Sstevel@tonic-gate 				}
2684*0Sstevel@tonic-gate 			}
2685*0Sstevel@tonic-gate 		if (reason == NULL)
2686*0Sstevel@tonic-gate 			{
2687*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2688*0Sstevel@tonic-gate 			return NULL;
2689*0Sstevel@tonic-gate 			}
2690*0Sstevel@tonic-gate 		break;
2691*0Sstevel@tonic-gate 
2692*0Sstevel@tonic-gate 	case REV_HOLD:
2693*0Sstevel@tonic-gate 		/* Argument is an OID */
2694*0Sstevel@tonic-gate 
2695*0Sstevel@tonic-gate 		otmp = OBJ_txt2obj(rev_arg, 0);
2696*0Sstevel@tonic-gate 		ASN1_OBJECT_free(otmp);
2697*0Sstevel@tonic-gate 
2698*0Sstevel@tonic-gate 		if (otmp == NULL)
2699*0Sstevel@tonic-gate 			{
2700*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2701*0Sstevel@tonic-gate 			return NULL;
2702*0Sstevel@tonic-gate 			}
2703*0Sstevel@tonic-gate 
2704*0Sstevel@tonic-gate 		reason = "holdInstruction";
2705*0Sstevel@tonic-gate 		other = rev_arg;
2706*0Sstevel@tonic-gate 		break;
2707*0Sstevel@tonic-gate 
2708*0Sstevel@tonic-gate 	case REV_KEY_COMPROMISE:
2709*0Sstevel@tonic-gate 	case REV_CA_COMPROMISE:
2710*0Sstevel@tonic-gate 
2711*0Sstevel@tonic-gate 		/* Argument is the key compromise time  */
2712*0Sstevel@tonic-gate 		if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2713*0Sstevel@tonic-gate 			{
2714*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2715*0Sstevel@tonic-gate 			return NULL;
2716*0Sstevel@tonic-gate 			}
2717*0Sstevel@tonic-gate 		other = rev_arg;
2718*0Sstevel@tonic-gate 		if (rev_type == REV_KEY_COMPROMISE)
2719*0Sstevel@tonic-gate 			reason = "keyTime";
2720*0Sstevel@tonic-gate 		else
2721*0Sstevel@tonic-gate 			reason = "CAkeyTime";
2722*0Sstevel@tonic-gate 
2723*0Sstevel@tonic-gate 		break;
2724*0Sstevel@tonic-gate 
2725*0Sstevel@tonic-gate 		}
2726*0Sstevel@tonic-gate 
2727*0Sstevel@tonic-gate 	revtm = X509_gmtime_adj(NULL, 0);
2728*0Sstevel@tonic-gate 
2729*0Sstevel@tonic-gate 	i = revtm->length + 1;
2730*0Sstevel@tonic-gate 
2731*0Sstevel@tonic-gate 	if (reason) i += strlen(reason) + 1;
2732*0Sstevel@tonic-gate 	if (other) i += strlen(other) + 1;
2733*0Sstevel@tonic-gate 
2734*0Sstevel@tonic-gate 	str = OPENSSL_malloc(i);
2735*0Sstevel@tonic-gate 
2736*0Sstevel@tonic-gate 	if (!str) return NULL;
2737*0Sstevel@tonic-gate 
2738*0Sstevel@tonic-gate 	BUF_strlcpy(str, (char *)revtm->data, i);
2739*0Sstevel@tonic-gate 	if (reason)
2740*0Sstevel@tonic-gate 		{
2741*0Sstevel@tonic-gate 		BUF_strlcat(str, ",", i);
2742*0Sstevel@tonic-gate 		BUF_strlcat(str, reason, i);
2743*0Sstevel@tonic-gate 		}
2744*0Sstevel@tonic-gate 	if (other)
2745*0Sstevel@tonic-gate 		{
2746*0Sstevel@tonic-gate 		BUF_strlcat(str, ",", i);
2747*0Sstevel@tonic-gate 		BUF_strlcat(str, other, i);
2748*0Sstevel@tonic-gate 		}
2749*0Sstevel@tonic-gate 	ASN1_UTCTIME_free(revtm);
2750*0Sstevel@tonic-gate 	return str;
2751*0Sstevel@tonic-gate 	}
2752*0Sstevel@tonic-gate 
2753*0Sstevel@tonic-gate /* Convert revocation field to X509_REVOKED entry
2754*0Sstevel@tonic-gate  * return code:
2755*0Sstevel@tonic-gate  * 0 error
2756*0Sstevel@tonic-gate  * 1 OK
2757*0Sstevel@tonic-gate  * 2 OK and some extensions added (i.e. V2 CRL)
2758*0Sstevel@tonic-gate  */
2759*0Sstevel@tonic-gate 
2760*0Sstevel@tonic-gate 
2761*0Sstevel@tonic-gate int make_revoked(X509_REVOKED *rev, char *str)
2762*0Sstevel@tonic-gate 	{
2763*0Sstevel@tonic-gate 	char *tmp = NULL;
2764*0Sstevel@tonic-gate 	int reason_code = -1;
2765*0Sstevel@tonic-gate 	int i, ret = 0;
2766*0Sstevel@tonic-gate 	ASN1_OBJECT *hold = NULL;
2767*0Sstevel@tonic-gate 	ASN1_GENERALIZEDTIME *comp_time = NULL;
2768*0Sstevel@tonic-gate 	ASN1_ENUMERATED *rtmp = NULL;
2769*0Sstevel@tonic-gate 
2770*0Sstevel@tonic-gate 	ASN1_TIME *revDate = NULL;
2771*0Sstevel@tonic-gate 
2772*0Sstevel@tonic-gate 	i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2773*0Sstevel@tonic-gate 
2774*0Sstevel@tonic-gate 	if (i == 0)
2775*0Sstevel@tonic-gate 		goto err;
2776*0Sstevel@tonic-gate 
2777*0Sstevel@tonic-gate 	if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2778*0Sstevel@tonic-gate 		goto err;
2779*0Sstevel@tonic-gate 
2780*0Sstevel@tonic-gate 	if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2781*0Sstevel@tonic-gate 		{
2782*0Sstevel@tonic-gate 		rtmp = ASN1_ENUMERATED_new();
2783*0Sstevel@tonic-gate 		if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2784*0Sstevel@tonic-gate 			goto err;
2785*0Sstevel@tonic-gate 		if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2786*0Sstevel@tonic-gate 			goto err;
2787*0Sstevel@tonic-gate 		}
2788*0Sstevel@tonic-gate 
2789*0Sstevel@tonic-gate 	if (rev && comp_time)
2790*0Sstevel@tonic-gate 		{
2791*0Sstevel@tonic-gate 		if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2792*0Sstevel@tonic-gate 			goto err;
2793*0Sstevel@tonic-gate 		}
2794*0Sstevel@tonic-gate 	if (rev && hold)
2795*0Sstevel@tonic-gate 		{
2796*0Sstevel@tonic-gate 		if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2797*0Sstevel@tonic-gate 			goto err;
2798*0Sstevel@tonic-gate 		}
2799*0Sstevel@tonic-gate 
2800*0Sstevel@tonic-gate 	if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2801*0Sstevel@tonic-gate 		ret = 2;
2802*0Sstevel@tonic-gate 	else ret = 1;
2803*0Sstevel@tonic-gate 
2804*0Sstevel@tonic-gate 	err:
2805*0Sstevel@tonic-gate 
2806*0Sstevel@tonic-gate 	if (tmp) OPENSSL_free(tmp);
2807*0Sstevel@tonic-gate 	ASN1_OBJECT_free(hold);
2808*0Sstevel@tonic-gate 	ASN1_GENERALIZEDTIME_free(comp_time);
2809*0Sstevel@tonic-gate 	ASN1_ENUMERATED_free(rtmp);
2810*0Sstevel@tonic-gate 	ASN1_TIME_free(revDate);
2811*0Sstevel@tonic-gate 
2812*0Sstevel@tonic-gate 	return ret;
2813*0Sstevel@tonic-gate 	}
2814*0Sstevel@tonic-gate 
2815*0Sstevel@tonic-gate /*
2816*0Sstevel@tonic-gate  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
2817*0Sstevel@tonic-gate  * where characters may be escaped by \
2818*0Sstevel@tonic-gate  */
2819*0Sstevel@tonic-gate X509_NAME *do_subject(char *subject, long chtype)
2820*0Sstevel@tonic-gate 	{
2821*0Sstevel@tonic-gate 	size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
2822*0Sstevel@tonic-gate 	char *buf = OPENSSL_malloc(buflen);
2823*0Sstevel@tonic-gate 	size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
2824*0Sstevel@tonic-gate 	char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
2825*0Sstevel@tonic-gate 	char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
2826*0Sstevel@tonic-gate 
2827*0Sstevel@tonic-gate 	char *sp = subject, *bp = buf;
2828*0Sstevel@tonic-gate 	int i, ne_num = 0;
2829*0Sstevel@tonic-gate 
2830*0Sstevel@tonic-gate 	X509_NAME *n = NULL;
2831*0Sstevel@tonic-gate 	int nid;
2832*0Sstevel@tonic-gate 
2833*0Sstevel@tonic-gate 	if (!buf || !ne_types || !ne_values)
2834*0Sstevel@tonic-gate 	{
2835*0Sstevel@tonic-gate 		BIO_printf(bio_err, "malloc error\n");
2836*0Sstevel@tonic-gate 		goto error;
2837*0Sstevel@tonic-gate 	}
2838*0Sstevel@tonic-gate 
2839*0Sstevel@tonic-gate 	if (*subject != '/')
2840*0Sstevel@tonic-gate 	{
2841*0Sstevel@tonic-gate 		BIO_printf(bio_err, "Subject does not start with '/'.\n");
2842*0Sstevel@tonic-gate 		goto error;
2843*0Sstevel@tonic-gate 	}
2844*0Sstevel@tonic-gate 	sp++; /* skip leading / */
2845*0Sstevel@tonic-gate 
2846*0Sstevel@tonic-gate 	while (*sp)
2847*0Sstevel@tonic-gate 		{
2848*0Sstevel@tonic-gate 		/* collect type */
2849*0Sstevel@tonic-gate 		ne_types[ne_num] = bp;
2850*0Sstevel@tonic-gate 		while (*sp)
2851*0Sstevel@tonic-gate 			{
2852*0Sstevel@tonic-gate 			if (*sp == '\\') /* is there anything to escape in the type...? */
2853*0Sstevel@tonic-gate 				{
2854*0Sstevel@tonic-gate 				if (*++sp)
2855*0Sstevel@tonic-gate 					*bp++ = *sp++;
2856*0Sstevel@tonic-gate 				else
2857*0Sstevel@tonic-gate 					{
2858*0Sstevel@tonic-gate 					BIO_printf(bio_err, "escape character at end of string\n");
2859*0Sstevel@tonic-gate 					goto error;
2860*0Sstevel@tonic-gate 					}
2861*0Sstevel@tonic-gate 				}
2862*0Sstevel@tonic-gate 			else if (*sp == '=')
2863*0Sstevel@tonic-gate 				{
2864*0Sstevel@tonic-gate 				sp++;
2865*0Sstevel@tonic-gate 				*bp++ = '\0';
2866*0Sstevel@tonic-gate 				break;
2867*0Sstevel@tonic-gate 				}
2868*0Sstevel@tonic-gate 			else
2869*0Sstevel@tonic-gate 				*bp++ = *sp++;
2870*0Sstevel@tonic-gate 			}
2871*0Sstevel@tonic-gate 		if (!*sp)
2872*0Sstevel@tonic-gate 			{
2873*0Sstevel@tonic-gate 			BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
2874*0Sstevel@tonic-gate 			goto error;
2875*0Sstevel@tonic-gate 			}
2876*0Sstevel@tonic-gate 		ne_values[ne_num] = bp;
2877*0Sstevel@tonic-gate 		while (*sp)
2878*0Sstevel@tonic-gate 			{
2879*0Sstevel@tonic-gate 			if (*sp == '\\')
2880*0Sstevel@tonic-gate 				{
2881*0Sstevel@tonic-gate 				if (*++sp)
2882*0Sstevel@tonic-gate 					*bp++ = *sp++;
2883*0Sstevel@tonic-gate 				else
2884*0Sstevel@tonic-gate 					{
2885*0Sstevel@tonic-gate 					BIO_printf(bio_err, "escape character at end of string\n");
2886*0Sstevel@tonic-gate 					goto error;
2887*0Sstevel@tonic-gate 					}
2888*0Sstevel@tonic-gate 				}
2889*0Sstevel@tonic-gate 			else if (*sp == '/')
2890*0Sstevel@tonic-gate 				{
2891*0Sstevel@tonic-gate 				sp++;
2892*0Sstevel@tonic-gate 				break;
2893*0Sstevel@tonic-gate 				}
2894*0Sstevel@tonic-gate 			else
2895*0Sstevel@tonic-gate 				*bp++ = *sp++;
2896*0Sstevel@tonic-gate 			}
2897*0Sstevel@tonic-gate 		*bp++ = '\0';
2898*0Sstevel@tonic-gate 		ne_num++;
2899*0Sstevel@tonic-gate 		}
2900*0Sstevel@tonic-gate 
2901*0Sstevel@tonic-gate 	if (!(n = X509_NAME_new()))
2902*0Sstevel@tonic-gate 		goto error;
2903*0Sstevel@tonic-gate 
2904*0Sstevel@tonic-gate 	for (i = 0; i < ne_num; i++)
2905*0Sstevel@tonic-gate 		{
2906*0Sstevel@tonic-gate 		if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
2907*0Sstevel@tonic-gate 			{
2908*0Sstevel@tonic-gate 			BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
2909*0Sstevel@tonic-gate 			continue;
2910*0Sstevel@tonic-gate 			}
2911*0Sstevel@tonic-gate 
2912*0Sstevel@tonic-gate 		if (!*ne_values[i])
2913*0Sstevel@tonic-gate 			{
2914*0Sstevel@tonic-gate 			BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
2915*0Sstevel@tonic-gate 			continue;
2916*0Sstevel@tonic-gate 			}
2917*0Sstevel@tonic-gate 
2918*0Sstevel@tonic-gate 		if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
2919*0Sstevel@tonic-gate 			goto error;
2920*0Sstevel@tonic-gate 		}
2921*0Sstevel@tonic-gate 
2922*0Sstevel@tonic-gate 	OPENSSL_free(ne_values);
2923*0Sstevel@tonic-gate 	OPENSSL_free(ne_types);
2924*0Sstevel@tonic-gate 	OPENSSL_free(buf);
2925*0Sstevel@tonic-gate 	return n;
2926*0Sstevel@tonic-gate 
2927*0Sstevel@tonic-gate error:
2928*0Sstevel@tonic-gate 	X509_NAME_free(n);
2929*0Sstevel@tonic-gate 	if (ne_values)
2930*0Sstevel@tonic-gate 		OPENSSL_free(ne_values);
2931*0Sstevel@tonic-gate 	if (ne_types)
2932*0Sstevel@tonic-gate 		OPENSSL_free(ne_types);
2933*0Sstevel@tonic-gate 	if (buf)
2934*0Sstevel@tonic-gate 		OPENSSL_free(buf);
2935*0Sstevel@tonic-gate 	return NULL;
2936*0Sstevel@tonic-gate }
2937*0Sstevel@tonic-gate 
2938*0Sstevel@tonic-gate int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2939*0Sstevel@tonic-gate 	{
2940*0Sstevel@tonic-gate 	char buf[25],*pbuf, *p;
2941*0Sstevel@tonic-gate 	int j;
2942*0Sstevel@tonic-gate 	j=i2a_ASN1_OBJECT(bp,obj);
2943*0Sstevel@tonic-gate 	pbuf=buf;
2944*0Sstevel@tonic-gate 	for (j=22-j; j>0; j--)
2945*0Sstevel@tonic-gate 		*(pbuf++)=' ';
2946*0Sstevel@tonic-gate 	*(pbuf++)=':';
2947*0Sstevel@tonic-gate 	*(pbuf++)='\0';
2948*0Sstevel@tonic-gate 	BIO_puts(bp,buf);
2949*0Sstevel@tonic-gate 
2950*0Sstevel@tonic-gate 	if (str->type == V_ASN1_PRINTABLESTRING)
2951*0Sstevel@tonic-gate 		BIO_printf(bp,"PRINTABLE:'");
2952*0Sstevel@tonic-gate 	else if (str->type == V_ASN1_T61STRING)
2953*0Sstevel@tonic-gate 		BIO_printf(bp,"T61STRING:'");
2954*0Sstevel@tonic-gate 	else if (str->type == V_ASN1_IA5STRING)
2955*0Sstevel@tonic-gate 		BIO_printf(bp,"IA5STRING:'");
2956*0Sstevel@tonic-gate 	else if (str->type == V_ASN1_UNIVERSALSTRING)
2957*0Sstevel@tonic-gate 		BIO_printf(bp,"UNIVERSALSTRING:'");
2958*0Sstevel@tonic-gate 	else
2959*0Sstevel@tonic-gate 		BIO_printf(bp,"ASN.1 %2d:'",str->type);
2960*0Sstevel@tonic-gate 
2961*0Sstevel@tonic-gate 	p=(char *)str->data;
2962*0Sstevel@tonic-gate 	for (j=str->length; j>0; j--)
2963*0Sstevel@tonic-gate 		{
2964*0Sstevel@tonic-gate 		if ((*p >= ' ') && (*p <= '~'))
2965*0Sstevel@tonic-gate 			BIO_printf(bp,"%c",*p);
2966*0Sstevel@tonic-gate 		else if (*p & 0x80)
2967*0Sstevel@tonic-gate 			BIO_printf(bp,"\\0x%02X",*p);
2968*0Sstevel@tonic-gate 		else if ((unsigned char)*p == 0xf7)
2969*0Sstevel@tonic-gate 			BIO_printf(bp,"^?");
2970*0Sstevel@tonic-gate 		else	BIO_printf(bp,"^%c",*p+'@');
2971*0Sstevel@tonic-gate 		p++;
2972*0Sstevel@tonic-gate 		}
2973*0Sstevel@tonic-gate 	BIO_printf(bp,"'\n");
2974*0Sstevel@tonic-gate 	return 1;
2975*0Sstevel@tonic-gate 	}
2976*0Sstevel@tonic-gate 
2977*0Sstevel@tonic-gate int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
2978*0Sstevel@tonic-gate 	{
2979*0Sstevel@tonic-gate 	char *tmp = NULL;
2980*0Sstevel@tonic-gate 	char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2981*0Sstevel@tonic-gate 	int reason_code = -1;
2982*0Sstevel@tonic-gate 	int i, ret = 0;
2983*0Sstevel@tonic-gate 	ASN1_OBJECT *hold = NULL;
2984*0Sstevel@tonic-gate 	ASN1_GENERALIZEDTIME *comp_time = NULL;
2985*0Sstevel@tonic-gate 	tmp = BUF_strdup(str);
2986*0Sstevel@tonic-gate 
2987*0Sstevel@tonic-gate 	p = strchr(tmp, ',');
2988*0Sstevel@tonic-gate 
2989*0Sstevel@tonic-gate 	rtime_str = tmp;
2990*0Sstevel@tonic-gate 
2991*0Sstevel@tonic-gate 	if (p)
2992*0Sstevel@tonic-gate 		{
2993*0Sstevel@tonic-gate 		*p = '\0';
2994*0Sstevel@tonic-gate 		p++;
2995*0Sstevel@tonic-gate 		reason_str = p;
2996*0Sstevel@tonic-gate 		p = strchr(p, ',');
2997*0Sstevel@tonic-gate 		if (p)
2998*0Sstevel@tonic-gate 			{
2999*0Sstevel@tonic-gate 			*p = '\0';
3000*0Sstevel@tonic-gate 			arg_str = p + 1;
3001*0Sstevel@tonic-gate 			}
3002*0Sstevel@tonic-gate 		}
3003*0Sstevel@tonic-gate 
3004*0Sstevel@tonic-gate 	if (prevtm)
3005*0Sstevel@tonic-gate 		{
3006*0Sstevel@tonic-gate 		*prevtm = ASN1_UTCTIME_new();
3007*0Sstevel@tonic-gate 		if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3008*0Sstevel@tonic-gate 			{
3009*0Sstevel@tonic-gate 			BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3010*0Sstevel@tonic-gate 			goto err;
3011*0Sstevel@tonic-gate 			}
3012*0Sstevel@tonic-gate 		}
3013*0Sstevel@tonic-gate 	if (reason_str)
3014*0Sstevel@tonic-gate 		{
3015*0Sstevel@tonic-gate 		for (i = 0; i < NUM_REASONS; i++)
3016*0Sstevel@tonic-gate 			{
3017*0Sstevel@tonic-gate 			if(!strcasecmp(reason_str, crl_reasons[i]))
3018*0Sstevel@tonic-gate 				{
3019*0Sstevel@tonic-gate 				reason_code = i;
3020*0Sstevel@tonic-gate 				break;
3021*0Sstevel@tonic-gate 				}
3022*0Sstevel@tonic-gate 			}
3023*0Sstevel@tonic-gate 		if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3024*0Sstevel@tonic-gate 			{
3025*0Sstevel@tonic-gate 			BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3026*0Sstevel@tonic-gate 			goto err;
3027*0Sstevel@tonic-gate 			}
3028*0Sstevel@tonic-gate 
3029*0Sstevel@tonic-gate 		if (reason_code == 7)
3030*0Sstevel@tonic-gate 			reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3031*0Sstevel@tonic-gate 		else if (reason_code == 8)		/* Hold instruction */
3032*0Sstevel@tonic-gate 			{
3033*0Sstevel@tonic-gate 			if (!arg_str)
3034*0Sstevel@tonic-gate 				{
3035*0Sstevel@tonic-gate 				BIO_printf(bio_err, "missing hold instruction\n");
3036*0Sstevel@tonic-gate 				goto err;
3037*0Sstevel@tonic-gate 				}
3038*0Sstevel@tonic-gate 			reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3039*0Sstevel@tonic-gate 			hold = OBJ_txt2obj(arg_str, 0);
3040*0Sstevel@tonic-gate 
3041*0Sstevel@tonic-gate 			if (!hold)
3042*0Sstevel@tonic-gate 				{
3043*0Sstevel@tonic-gate 				BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3044*0Sstevel@tonic-gate 				goto err;
3045*0Sstevel@tonic-gate 				}
3046*0Sstevel@tonic-gate 			if (phold) *phold = hold;
3047*0Sstevel@tonic-gate 			}
3048*0Sstevel@tonic-gate 		else if ((reason_code == 9) || (reason_code == 10))
3049*0Sstevel@tonic-gate 			{
3050*0Sstevel@tonic-gate 			if (!arg_str)
3051*0Sstevel@tonic-gate 				{
3052*0Sstevel@tonic-gate 				BIO_printf(bio_err, "missing compromised time\n");
3053*0Sstevel@tonic-gate 				goto err;
3054*0Sstevel@tonic-gate 				}
3055*0Sstevel@tonic-gate 			comp_time = ASN1_GENERALIZEDTIME_new();
3056*0Sstevel@tonic-gate 			if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3057*0Sstevel@tonic-gate 				{
3058*0Sstevel@tonic-gate 				BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3059*0Sstevel@tonic-gate 				goto err;
3060*0Sstevel@tonic-gate 				}
3061*0Sstevel@tonic-gate 			if (reason_code == 9)
3062*0Sstevel@tonic-gate 				reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3063*0Sstevel@tonic-gate 			else
3064*0Sstevel@tonic-gate 				reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3065*0Sstevel@tonic-gate 			}
3066*0Sstevel@tonic-gate 		}
3067*0Sstevel@tonic-gate 
3068*0Sstevel@tonic-gate 	if (preason) *preason = reason_code;
3069*0Sstevel@tonic-gate 	if (pinvtm) *pinvtm = comp_time;
3070*0Sstevel@tonic-gate 	else ASN1_GENERALIZEDTIME_free(comp_time);
3071*0Sstevel@tonic-gate 
3072*0Sstevel@tonic-gate 	ret = 1;
3073*0Sstevel@tonic-gate 
3074*0Sstevel@tonic-gate 	err:
3075*0Sstevel@tonic-gate 
3076*0Sstevel@tonic-gate 	if (tmp) OPENSSL_free(tmp);
3077*0Sstevel@tonic-gate 	if (!phold) ASN1_OBJECT_free(hold);
3078*0Sstevel@tonic-gate 	if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3079*0Sstevel@tonic-gate 
3080*0Sstevel@tonic-gate 	return ret;
3081*0Sstevel@tonic-gate 	}
3082