req.c revision 267285
155714Skris/* apps/req.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59160814Ssimon/* Until the key-gen callbacks are modified to use newer prototypes, we allow
60160814Ssimon * deprecated functions for openssl-internal code */
61160814Ssimon#ifdef OPENSSL_NO_DEPRECATED
62160814Ssimon#undef OPENSSL_NO_DEPRECATED
63160814Ssimon#endif
64160814Ssimon
6555714Skris#include <stdio.h>
6655714Skris#include <stdlib.h>
6755714Skris#include <time.h>
6855714Skris#include <string.h>
69109998Smarkm#ifdef OPENSSL_NO_STDIO
7055714Skris#define APPS_WIN16
7155714Skris#endif
7255714Skris#include "apps.h"
7355714Skris#include <openssl/bio.h>
7455714Skris#include <openssl/evp.h>
7555714Skris#include <openssl/conf.h>
7655714Skris#include <openssl/err.h>
7755714Skris#include <openssl/asn1.h>
7855714Skris#include <openssl/x509.h>
7955714Skris#include <openssl/x509v3.h>
8055714Skris#include <openssl/objects.h>
8155714Skris#include <openssl/pem.h>
82160814Ssimon#include <openssl/bn.h>
83160814Ssimon#ifndef OPENSSL_NO_RSA
84160814Ssimon#include <openssl/rsa.h>
85160814Ssimon#endif
86160814Ssimon#ifndef OPENSSL_NO_DSA
87160814Ssimon#include <openssl/dsa.h>
88160814Ssimon#endif
8955714Skris
9055714Skris#define SECTION		"req"
9155714Skris
9255714Skris#define BITS		"default_bits"
9355714Skris#define KEYFILE		"default_keyfile"
9459191Skris#define PROMPT		"prompt"
9555714Skris#define DISTINGUISHED_NAME	"distinguished_name"
9655714Skris#define ATTRIBUTES	"attributes"
9755714Skris#define V3_EXTENSIONS	"x509_extensions"
9859191Skris#define REQ_EXTENSIONS	"req_extensions"
9959191Skris#define STRING_MASK	"string_mask"
100109998Smarkm#define UTF8_IN		"utf8"
10155714Skris
10255714Skris#define DEFAULT_KEY_LENGTH	512
10355714Skris#define MIN_KEY_LENGTH		384
10455714Skris
10555714Skris#undef PROG
10655714Skris#define PROG	req_main
10755714Skris
10859191Skris/* -inform arg	- input format - default PEM (DER or PEM)
10955714Skris * -outform arg - output format - default PEM
11055714Skris * -in arg	- input file - default stdin
11155714Skris * -out arg	- output file - default stdout
11255714Skris * -verify	- check request signature
11355714Skris * -noout	- don't print stuff out.
11455714Skris * -text	- print out human readable text.
11555714Skris * -nodes	- no des encryption
11655714Skris * -config file	- Load configuration file.
11755714Skris * -key file	- make a request using key in file (or use it for verification).
118109998Smarkm * -keyform arg	- key file format.
11968651Skris * -rand file(s) - load the file(s) into the PRNG.
12055714Skris * -newkey	- make a key and a request.
12155714Skris * -modulus	- print RSA modulus.
122109998Smarkm * -pubkey	- output Public Key.
12355714Skris * -x509	- output a self signed X509 structure instead.
12455714Skris * -asn1-kludge	- output new certificate request in a format that some CA's
12555714Skris *		  require.  This format is wrong
12655714Skris */
12755714Skris
128160814Ssimonstatic int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn,
129160814Ssimon		int attribs,unsigned long chtype);
130160814Ssimonstatic int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
131160814Ssimon		int multirdn);
13259191Skrisstatic int prompt_info(X509_REQ *req,
13359191Skris		STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
134109998Smarkm		STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
135109998Smarkm		unsigned long chtype);
13659191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
137109998Smarkm				STACK_OF(CONF_VALUE) *attr, int attribs,
138109998Smarkm				unsigned long chtype);
139160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
140160814Ssimon				char *value, int nid, int n_min,
141109998Smarkm				int n_max, unsigned long chtype);
142160814Ssimonstatic int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
143160814Ssimon	int nid,int n_min,int n_max, unsigned long chtype, int mval);
144109998Smarkm#ifndef OPENSSL_NO_RSA
145160814Ssimonstatic int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb);
14659191Skris#endif
147109998Smarkmstatic int req_check_len(int len,int n_min,int n_max);
148160814Ssimonstatic int check_end(const char *str, const char *end);
14955714Skris#ifndef MONOLITH
15055714Skrisstatic char *default_config_file=NULL;
15155714Skris#endif
152109998Smarkmstatic CONF *req_conf=NULL;
153109998Smarkmstatic int batch=0;
15455714Skris
15555714Skris#define TYPE_RSA	1
15655714Skris#define TYPE_DSA	2
15755714Skris#define TYPE_DH		3
158160814Ssimon#define TYPE_EC		4
15955714Skris
16059191Skrisint MAIN(int, char **);
16159191Skris
16255714Skrisint MAIN(int argc, char **argv)
16355714Skris	{
164109998Smarkm	ENGINE *e = NULL;
165109998Smarkm#ifndef OPENSSL_NO_DSA
16655714Skris	DSA *dsa_params=NULL;
16755714Skris#endif
168160814Ssimon#ifndef OPENSSL_NO_ECDSA
169160814Ssimon	EC_KEY *ec_params = NULL;
170160814Ssimon#endif
171109998Smarkm	unsigned long nmflag = 0, reqflag = 0;
17255714Skris	int ex=1,x509=0,days=30;
17355714Skris	X509 *x509ss=NULL;
17455714Skris	X509_REQ *req=NULL;
17555714Skris	EVP_PKEY *pkey=NULL;
176109998Smarkm	int i=0,badops=0,newreq=0,verbose=0,pkey_type=TYPE_RSA;
177109998Smarkm	long newkey = -1;
17855714Skris	BIO *in=NULL,*out=NULL;
17955714Skris	int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
180109998Smarkm	int nodes=0,kludge=0,newhdr=0,subject=0,pubkey=0;
18155714Skris	char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
182111147Snectar#ifndef OPENSSL_NO_ENGINE
183109998Smarkm	char *engine=NULL;
184111147Snectar#endif
18555714Skris	char *extensions = NULL;
18659191Skris	char *req_exts = NULL;
187109998Smarkm	const EVP_CIPHER *cipher=NULL;
188109998Smarkm	ASN1_INTEGER *serial = NULL;
18955714Skris	int modulus=0;
19068651Skris	char *inrand=NULL;
19159191Skris	char *passargin = NULL, *passargout = NULL;
19259191Skris	char *passin = NULL, *passout = NULL;
19355714Skris	char *p;
194109998Smarkm	char *subj = NULL;
195160814Ssimon	int multirdn = 0;
196160814Ssimon	const EVP_MD *md_alg=NULL,*digest=EVP_sha1();
197109998Smarkm	unsigned long chtype = MBSTRING_ASC;
19855714Skris#ifndef MONOLITH
199109998Smarkm	char *to_free;
200109998Smarkm	long errline;
20155714Skris#endif
20255714Skris
20359191Skris	req_conf = NULL;
204109998Smarkm#ifndef OPENSSL_NO_DES
20555714Skris	cipher=EVP_des_ede3_cbc();
20655714Skris#endif
20755714Skris	apps_startup();
20855714Skris
20955714Skris	if (bio_err == NULL)
21055714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
21155714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
21255714Skris
21355714Skris	infile=NULL;
21455714Skris	outfile=NULL;
21555714Skris	informat=FORMAT_PEM;
21655714Skris	outformat=FORMAT_PEM;
21755714Skris
21855714Skris	prog=argv[0];
21955714Skris	argc--;
22055714Skris	argv++;
22155714Skris	while (argc >= 1)
22255714Skris		{
22355714Skris		if 	(strcmp(*argv,"-inform") == 0)
22455714Skris			{
22555714Skris			if (--argc < 1) goto bad;
22655714Skris			informat=str2fmt(*(++argv));
22755714Skris			}
22855714Skris		else if (strcmp(*argv,"-outform") == 0)
22955714Skris			{
23055714Skris			if (--argc < 1) goto bad;
23155714Skris			outformat=str2fmt(*(++argv));
23255714Skris			}
233111147Snectar#ifndef OPENSSL_NO_ENGINE
234109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
235109998Smarkm			{
236109998Smarkm			if (--argc < 1) goto bad;
237109998Smarkm			engine= *(++argv);
238109998Smarkm			}
239111147Snectar#endif
24055714Skris		else if (strcmp(*argv,"-key") == 0)
24155714Skris			{
24255714Skris			if (--argc < 1) goto bad;
24355714Skris			keyfile= *(++argv);
24455714Skris			}
245109998Smarkm		else if (strcmp(*argv,"-pubkey") == 0)
246109998Smarkm			{
247109998Smarkm			pubkey=1;
248109998Smarkm			}
24955714Skris		else if (strcmp(*argv,"-new") == 0)
25055714Skris			{
25155714Skris			newreq=1;
25255714Skris			}
25355714Skris		else if (strcmp(*argv,"-config") == 0)
25455714Skris			{
25555714Skris			if (--argc < 1) goto bad;
25655714Skris			template= *(++argv);
25755714Skris			}
25855714Skris		else if (strcmp(*argv,"-keyform") == 0)
25955714Skris			{
26055714Skris			if (--argc < 1) goto bad;
26155714Skris			keyform=str2fmt(*(++argv));
26255714Skris			}
26355714Skris		else if (strcmp(*argv,"-in") == 0)
26455714Skris			{
26555714Skris			if (--argc < 1) goto bad;
26655714Skris			infile= *(++argv);
26755714Skris			}
26855714Skris		else if (strcmp(*argv,"-out") == 0)
26955714Skris			{
27055714Skris			if (--argc < 1) goto bad;
27155714Skris			outfile= *(++argv);
27255714Skris			}
27355714Skris		else if (strcmp(*argv,"-keyout") == 0)
27455714Skris			{
27555714Skris			if (--argc < 1) goto bad;
27655714Skris			keyout= *(++argv);
27755714Skris			}
27859191Skris		else if (strcmp(*argv,"-passin") == 0)
27959191Skris			{
28059191Skris			if (--argc < 1) goto bad;
28159191Skris			passargin= *(++argv);
28259191Skris			}
28359191Skris		else if (strcmp(*argv,"-passout") == 0)
28459191Skris			{
28559191Skris			if (--argc < 1) goto bad;
28659191Skris			passargout= *(++argv);
28759191Skris			}
28868651Skris		else if (strcmp(*argv,"-rand") == 0)
28968651Skris			{
29068651Skris			if (--argc < 1) goto bad;
29168651Skris			inrand= *(++argv);
29268651Skris			}
29355714Skris		else if (strcmp(*argv,"-newkey") == 0)
29455714Skris			{
29555714Skris			int is_numeric;
29655714Skris
29755714Skris			if (--argc < 1) goto bad;
29855714Skris			p= *(++argv);
29955714Skris			is_numeric = p[0] >= '0' && p[0] <= '9';
30055714Skris			if (strncmp("rsa:",p,4) == 0 || is_numeric)
30155714Skris				{
30255714Skris				pkey_type=TYPE_RSA;
30355714Skris				if(!is_numeric)
30455714Skris				    p+=4;
30555714Skris				newkey= atoi(p);
30655714Skris				}
30755714Skris			else
308109998Smarkm#ifndef OPENSSL_NO_DSA
30955714Skris				if (strncmp("dsa:",p,4) == 0)
31055714Skris				{
31155714Skris				X509 *xtmp=NULL;
31255714Skris				EVP_PKEY *dtmp;
31355714Skris
31455714Skris				pkey_type=TYPE_DSA;
31555714Skris				p+=4;
31655714Skris				if ((in=BIO_new_file(p,"r")) == NULL)
31755714Skris					{
31855714Skris					perror(p);
31955714Skris					goto end;
32055714Skris					}
32155714Skris				if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
32255714Skris					{
32355714Skris					ERR_clear_error();
32455714Skris					(void)BIO_reset(in);
32555714Skris					if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
32655714Skris						{
32755714Skris						BIO_printf(bio_err,"unable to load DSA parameters from file\n");
32855714Skris						goto end;
32955714Skris						}
33055714Skris
331100928Snectar					if ((dtmp=X509_get_pubkey(xtmp)) == NULL) goto end;
33255714Skris					if (dtmp->type == EVP_PKEY_DSA)
33355714Skris						dsa_params=DSAparams_dup(dtmp->pkey.dsa);
33455714Skris					EVP_PKEY_free(dtmp);
33555714Skris					X509_free(xtmp);
33655714Skris					if (dsa_params == NULL)
33755714Skris						{
33855714Skris						BIO_printf(bio_err,"Certificate does not contain DSA parameters\n");
33955714Skris						goto end;
34055714Skris						}
34155714Skris					}
34255714Skris				BIO_free(in);
343160814Ssimon				in=NULL;
34455714Skris				newkey=BN_num_bits(dsa_params->p);
34555714Skris				}
34655714Skris			else
34755714Skris#endif
348160814Ssimon#ifndef OPENSSL_NO_ECDSA
349160814Ssimon				if (strncmp("ec:",p,3) == 0)
350160814Ssimon				{
351160814Ssimon				X509 *xtmp=NULL;
352160814Ssimon				EVP_PKEY *dtmp;
353160814Ssimon				EC_GROUP *group;
354160814Ssimon
355160814Ssimon				pkey_type=TYPE_EC;
356160814Ssimon				p+=3;
357160814Ssimon				if ((in=BIO_new_file(p,"r")) == NULL)
358160814Ssimon					{
359160814Ssimon					perror(p);
360160814Ssimon					goto end;
361160814Ssimon					}
362160814Ssimon				if ((ec_params = EC_KEY_new()) == NULL)
363160814Ssimon					goto end;
364160814Ssimon				group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
365160814Ssimon				if (group == NULL)
366160814Ssimon					{
367160814Ssimon					EC_KEY_free(ec_params);
368160814Ssimon					ERR_clear_error();
369160814Ssimon					(void)BIO_reset(in);
370160814Ssimon					if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
371160814Ssimon						{
372160814Ssimon						BIO_printf(bio_err,"unable to load EC parameters from file\n");
373160814Ssimon						goto end;
374160814Ssimon						}
375160814Ssimon
376160814Ssimon					if ((dtmp=X509_get_pubkey(xtmp))==NULL)
377160814Ssimon						goto end;
378160814Ssimon					if (dtmp->type == EVP_PKEY_EC)
379160814Ssimon						ec_params = EC_KEY_dup(dtmp->pkey.ec);
380160814Ssimon					EVP_PKEY_free(dtmp);
381160814Ssimon					X509_free(xtmp);
382160814Ssimon					if (ec_params == NULL)
383160814Ssimon						{
384160814Ssimon						BIO_printf(bio_err,"Certificate does not contain EC parameters\n");
385160814Ssimon						goto end;
386160814Ssimon						}
387160814Ssimon					}
388160814Ssimon				else
389160814Ssimon					{
390160814Ssimon					if (EC_KEY_set_group(ec_params, group) == 0)
391160814Ssimon						goto end;
392160814Ssimon					EC_GROUP_free(group);
393160814Ssimon					}
394160814Ssimon
395160814Ssimon				BIO_free(in);
396160814Ssimon				in=NULL;
397160814Ssimon				newkey = EC_GROUP_get_degree(EC_KEY_get0_group(ec_params));
398160814Ssimon				}
399160814Ssimon			else
400160814Ssimon#endif
401109998Smarkm#ifndef OPENSSL_NO_DH
40255714Skris				if (strncmp("dh:",p,4) == 0)
40355714Skris				{
40455714Skris				pkey_type=TYPE_DH;
40555714Skris				p+=3;
40655714Skris				}
40755714Skris			else
40855714Skris#endif
409160814Ssimon				{
410160814Ssimon				goto bad;
411160814Ssimon				}
41255714Skris
41355714Skris			newreq=1;
41455714Skris			}
415109998Smarkm		else if (strcmp(*argv,"-batch") == 0)
416109998Smarkm			batch=1;
41759191Skris		else if (strcmp(*argv,"-newhdr") == 0)
41859191Skris			newhdr=1;
41955714Skris		else if (strcmp(*argv,"-modulus") == 0)
42055714Skris			modulus=1;
42155714Skris		else if (strcmp(*argv,"-verify") == 0)
42255714Skris			verify=1;
42355714Skris		else if (strcmp(*argv,"-nodes") == 0)
42455714Skris			nodes=1;
42555714Skris		else if (strcmp(*argv,"-noout") == 0)
42655714Skris			noout=1;
427109998Smarkm		else if (strcmp(*argv,"-verbose") == 0)
428109998Smarkm			verbose=1;
429109998Smarkm		else if (strcmp(*argv,"-utf8") == 0)
430109998Smarkm			chtype = MBSTRING_UTF8;
431109998Smarkm		else if (strcmp(*argv,"-nameopt") == 0)
432109998Smarkm			{
433109998Smarkm			if (--argc < 1) goto bad;
434109998Smarkm			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
435109998Smarkm			}
436109998Smarkm		else if (strcmp(*argv,"-reqopt") == 0)
437109998Smarkm			{
438109998Smarkm			if (--argc < 1) goto bad;
439109998Smarkm			if (!set_cert_ex(&reqflag, *(++argv))) goto bad;
440109998Smarkm			}
441109998Smarkm		else if (strcmp(*argv,"-subject") == 0)
442109998Smarkm			subject=1;
44355714Skris		else if (strcmp(*argv,"-text") == 0)
44455714Skris			text=1;
44555714Skris		else if (strcmp(*argv,"-x509") == 0)
44655714Skris			x509=1;
44755714Skris		else if (strcmp(*argv,"-asn1-kludge") == 0)
44855714Skris			kludge=1;
44955714Skris		else if (strcmp(*argv,"-no-asn1-kludge") == 0)
45055714Skris			kludge=0;
451109998Smarkm		else if (strcmp(*argv,"-subj") == 0)
452109998Smarkm			{
453109998Smarkm			if (--argc < 1) goto bad;
454109998Smarkm			subj= *(++argv);
455109998Smarkm			}
456160814Ssimon		else if (strcmp(*argv,"-multivalue-rdn") == 0)
457160814Ssimon			multirdn=1;
45855714Skris		else if (strcmp(*argv,"-days") == 0)
45955714Skris			{
46055714Skris			if (--argc < 1) goto bad;
46155714Skris			days= atoi(*(++argv));
46255714Skris			if (days == 0) days=30;
46355714Skris			}
464109998Smarkm		else if (strcmp(*argv,"-set_serial") == 0)
465109998Smarkm			{
466109998Smarkm			if (--argc < 1) goto bad;
467109998Smarkm			serial = s2i_ASN1_INTEGER(NULL, *(++argv));
468109998Smarkm			if (!serial) goto bad;
469109998Smarkm			}
47055714Skris		else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
47155714Skris			{
47255714Skris			/* ok */
47355714Skris			digest=md_alg;
47455714Skris			}
47559191Skris		else if (strcmp(*argv,"-extensions") == 0)
47659191Skris			{
47759191Skris			if (--argc < 1) goto bad;
47859191Skris			extensions = *(++argv);
47959191Skris			}
48059191Skris		else if (strcmp(*argv,"-reqexts") == 0)
48159191Skris			{
48259191Skris			if (--argc < 1) goto bad;
48359191Skris			req_exts = *(++argv);
48459191Skris			}
48555714Skris		else
48655714Skris			{
48755714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
48855714Skris			badops=1;
48955714Skris			break;
49055714Skris			}
49155714Skris		argc--;
49255714Skris		argv++;
49355714Skris		}
49455714Skris
49555714Skris	if (badops)
49655714Skris		{
49755714Skrisbad:
49855714Skris		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
49955714Skris		BIO_printf(bio_err,"where options  are\n");
50059191Skris		BIO_printf(bio_err," -inform arg    input format - DER or PEM\n");
50159191Skris		BIO_printf(bio_err," -outform arg   output format - DER or PEM\n");
50255714Skris		BIO_printf(bio_err," -in arg        input file\n");
50355714Skris		BIO_printf(bio_err," -out arg       output file\n");
50455714Skris		BIO_printf(bio_err," -text          text form of request\n");
505109998Smarkm		BIO_printf(bio_err," -pubkey        output public key\n");
50655714Skris		BIO_printf(bio_err," -noout         do not output REQ\n");
50755714Skris		BIO_printf(bio_err," -verify        verify signature on REQ\n");
50855714Skris		BIO_printf(bio_err," -modulus       RSA modulus\n");
50955714Skris		BIO_printf(bio_err," -nodes         don't encrypt the output key\n");
510111147Snectar#ifndef OPENSSL_NO_ENGINE
511109998Smarkm		BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device\n");
512111147Snectar#endif
513109998Smarkm		BIO_printf(bio_err," -subject       output the request's subject\n");
514109998Smarkm		BIO_printf(bio_err," -passin        private key password source\n");
515109998Smarkm		BIO_printf(bio_err," -key file      use the private key contained in file\n");
51655714Skris		BIO_printf(bio_err," -keyform arg   key file format\n");
51755714Skris		BIO_printf(bio_err," -keyout arg    file to send the key to\n");
51868651Skris		BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
51968651Skris		BIO_printf(bio_err,"                load the file (or the files in the directory) into\n");
52068651Skris		BIO_printf(bio_err,"                the random number generator\n");
52155714Skris		BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
52255714Skris		BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
523160814Ssimon#ifndef OPENSSL_NO_ECDSA
524160814Ssimon		BIO_printf(bio_err," -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n");
525160814Ssimon#endif
52689837Skris		BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
52755714Skris		BIO_printf(bio_err," -config file   request template file.\n");
528109998Smarkm		BIO_printf(bio_err," -subj arg      set or modify request subject\n");
529160814Ssimon		BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n");
53055714Skris		BIO_printf(bio_err," -new           new request.\n");
531109998Smarkm		BIO_printf(bio_err," -batch         do not ask anything during request generation\n");
53255714Skris		BIO_printf(bio_err," -x509          output a x509 structure instead of a cert. req.\n");
533109998Smarkm		BIO_printf(bio_err," -days          number of days a certificate generated by -x509 is valid for.\n");
534109998Smarkm		BIO_printf(bio_err," -set_serial    serial number to use for a certificate generated by -x509.\n");
53559191Skris		BIO_printf(bio_err," -newhdr        output \"NEW\" in the header lines\n");
53655714Skris		BIO_printf(bio_err," -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
53755714Skris		BIO_printf(bio_err,"                have been reported as requiring\n");
53859191Skris		BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
53959191Skris		BIO_printf(bio_err," -reqexts ..    specify request extension section (override value in config file)\n");
540109998Smarkm		BIO_printf(bio_err," -utf8          input characters are UTF8 (default ASCII)\n");
541111147Snectar		BIO_printf(bio_err," -nameopt arg    - various certificate name options\n");
542109998Smarkm		BIO_printf(bio_err," -reqopt arg    - various request text options\n\n");
54355714Skris		goto end;
54455714Skris		}
54555714Skris
54655714Skris	ERR_load_crypto_strings();
54759191Skris	if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
54859191Skris		BIO_printf(bio_err, "Error getting passwords\n");
54959191Skris		goto end;
55059191Skris	}
55155714Skris
55259191Skris#ifndef MONOLITH /* else this has happened in openssl.c (global `config') */
55355714Skris	/* Lets load up our environment a little */
55455714Skris	p=getenv("OPENSSL_CONF");
55555714Skris	if (p == NULL)
55655714Skris		p=getenv("SSLEAY_CONF");
55755714Skris	if (p == NULL)
558109998Smarkm		p=to_free=make_config_name();
55959191Skris	default_config_file=p;
560109998Smarkm	config=NCONF_new(NULL);
561109998Smarkm	i=NCONF_load(config, p, &errline);
56255714Skris#endif
56355714Skris
56455714Skris	if (template != NULL)
56555714Skris		{
566109998Smarkm		long errline = -1;
56755714Skris
568109998Smarkm		if( verbose )
569109998Smarkm			BIO_printf(bio_err,"Using configuration from %s\n",template);
570109998Smarkm		req_conf=NCONF_new(NULL);
571109998Smarkm		i=NCONF_load(req_conf,template,&errline);
572109998Smarkm		if (i == 0)
57355714Skris			{
57455714Skris			BIO_printf(bio_err,"error on line %ld of %s\n",errline,template);
57555714Skris			goto end;
57655714Skris			}
57755714Skris		}
57855714Skris	else
57955714Skris		{
58055714Skris		req_conf=config;
581160814Ssimon
58255714Skris		if (req_conf == NULL)
58355714Skris			{
584160814Ssimon			BIO_printf(bio_err,"Unable to load config info from %s\n", default_config_file);
585160814Ssimon			if (newreq)
586160814Ssimon				goto end;
58755714Skris			}
588160814Ssimon		else if( verbose )
589160814Ssimon			BIO_printf(bio_err,"Using configuration from %s\n",
590160814Ssimon			default_config_file);
59155714Skris		}
59255714Skris
59355714Skris	if (req_conf != NULL)
59455714Skris		{
595109998Smarkm		if (!load_config(bio_err, req_conf))
596109998Smarkm			goto end;
597109998Smarkm		p=NCONF_get_string(req_conf,NULL,"oid_file");
598109998Smarkm		if (p == NULL)
599109998Smarkm			ERR_clear_error();
60055714Skris		if (p != NULL)
60155714Skris			{
60255714Skris			BIO *oid_bio;
60355714Skris
60455714Skris			oid_bio=BIO_new_file(p,"r");
60555714Skris			if (oid_bio == NULL)
60655714Skris				{
60755714Skris				/*
60855714Skris				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
60955714Skris				ERR_print_errors(bio_err);
61055714Skris				*/
61155714Skris				}
61255714Skris			else
61355714Skris				{
61455714Skris				OBJ_create_objects(oid_bio);
61555714Skris				BIO_free(oid_bio);
61655714Skris				}
61755714Skris			}
61855714Skris		}
619109998Smarkm	if(!add_oid_section(bio_err, req_conf)) goto end;
62055714Skris
621109998Smarkm	if (md_alg == NULL)
62255714Skris		{
623109998Smarkm		p=NCONF_get_string(req_conf,SECTION,"default_md");
624109998Smarkm		if (p == NULL)
625109998Smarkm			ERR_clear_error();
626109998Smarkm		if (p != NULL)
627109998Smarkm			{
628109998Smarkm			if ((md_alg=EVP_get_digestbyname(p)) != NULL)
629109998Smarkm				digest=md_alg;
630109998Smarkm			}
63155714Skris		}
63255714Skris
633109998Smarkm	if (!extensions)
634109998Smarkm		{
635109998Smarkm		extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
636109998Smarkm		if (!extensions)
637109998Smarkm			ERR_clear_error();
638109998Smarkm		}
639109998Smarkm	if (extensions) {
64055714Skris		/* Check syntax of file */
64155714Skris		X509V3_CTX ctx;
64255714Skris		X509V3_set_ctx_test(&ctx);
643109998Smarkm		X509V3_set_nconf(&ctx, req_conf);
644109998Smarkm		if(!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
64555714Skris			BIO_printf(bio_err,
64655714Skris			 "Error Loading extension section %s\n", extensions);
64755714Skris			goto end;
64855714Skris		}
64955714Skris	}
65055714Skris
65159191Skris	if(!passin)
652109998Smarkm		{
653109998Smarkm		passin = NCONF_get_string(req_conf, SECTION, "input_password");
654109998Smarkm		if (!passin)
655109998Smarkm			ERR_clear_error();
656109998Smarkm		}
657109998Smarkm
65859191Skris	if(!passout)
659109998Smarkm		{
660109998Smarkm		passout = NCONF_get_string(req_conf, SECTION, "output_password");
661109998Smarkm		if (!passout)
662109998Smarkm			ERR_clear_error();
663109998Smarkm		}
66459191Skris
665109998Smarkm	p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
666109998Smarkm	if (!p)
667109998Smarkm		ERR_clear_error();
66859191Skris
66959191Skris	if(p && !ASN1_STRING_set_default_mask_asc(p)) {
67059191Skris		BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
67159191Skris		goto end;
67259191Skris	}
67359191Skris
674109998Smarkm	if (chtype != MBSTRING_UTF8)
675109998Smarkm		{
676109998Smarkm		p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
677109998Smarkm		if (!p)
678109998Smarkm			ERR_clear_error();
679109998Smarkm		else if (!strcmp(p, "yes"))
680109998Smarkm			chtype = MBSTRING_UTF8;
681109998Smarkm		}
682109998Smarkm
683109998Smarkm
68459191Skris	if(!req_exts)
685109998Smarkm		{
686109998Smarkm		req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
687109998Smarkm		if (!req_exts)
688109998Smarkm			ERR_clear_error();
689109998Smarkm		}
69059191Skris	if(req_exts) {
69159191Skris		/* Check syntax of file */
69259191Skris		X509V3_CTX ctx;
69359191Skris		X509V3_set_ctx_test(&ctx);
694109998Smarkm		X509V3_set_nconf(&ctx, req_conf);
695109998Smarkm		if(!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
69659191Skris			BIO_printf(bio_err,
69759191Skris			 "Error Loading request extension section %s\n",
69859191Skris								req_exts);
69959191Skris			goto end;
70059191Skris		}
70159191Skris	}
70259191Skris
70355714Skris	in=BIO_new(BIO_s_file());
70455714Skris	out=BIO_new(BIO_s_file());
70555714Skris	if ((in == NULL) || (out == NULL))
70655714Skris		goto end;
70755714Skris
708111147Snectar#ifndef OPENSSL_NO_ENGINE
709109998Smarkm        e = setup_engine(bio_err, engine, 0);
710111147Snectar#endif
711109998Smarkm
71255714Skris	if (keyfile != NULL)
71355714Skris		{
714109998Smarkm		pkey = load_key(bio_err, keyfile, keyform, 0, passin, e,
715109998Smarkm			"Private Key");
716109998Smarkm		if (!pkey)
71755714Skris			{
718109998Smarkm			/* load_key() has already printed an appropriate
719109998Smarkm			   message */
72055714Skris			goto end;
72155714Skris			}
722194206Ssimon		else
72359191Skris			{
724109998Smarkm			char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
725109998Smarkm			if (randfile == NULL)
726109998Smarkm				ERR_clear_error();
727109998Smarkm			app_RAND_load_file(randfile, bio_err, 0);
72859191Skris			}
72955714Skris		}
73055714Skris
73155714Skris	if (newreq && (pkey == NULL))
73255714Skris		{
733160814Ssimon#ifndef OPENSSL_NO_RSA
734160814Ssimon		BN_GENCB cb;
735160814Ssimon#endif
736109998Smarkm		char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
737109998Smarkm		if (randfile == NULL)
738109998Smarkm			ERR_clear_error();
73959191Skris		app_RAND_load_file(randfile, bio_err, 0);
74068651Skris		if (inrand)
74168651Skris			app_RAND_load_files(inrand);
74259191Skris
74355714Skris		if (newkey <= 0)
74455714Skris			{
745109998Smarkm			if (!NCONF_get_number(req_conf,SECTION,BITS, &newkey))
74655714Skris				newkey=DEFAULT_KEY_LENGTH;
74755714Skris			}
74855714Skris
749160814Ssimon		if (newkey < MIN_KEY_LENGTH && (pkey_type == TYPE_RSA || pkey_type == TYPE_DSA))
75055714Skris			{
75155714Skris			BIO_printf(bio_err,"private key length is too short,\n");
752160814Ssimon			BIO_printf(bio_err,"it needs to be at least %d bits, not %ld\n",MIN_KEY_LENGTH,newkey);
75355714Skris			goto end;
75455714Skris			}
755160814Ssimon		BIO_printf(bio_err,"Generating a %ld bit %s private key\n",
756160814Ssimon			newkey,(pkey_type == TYPE_RSA)?"RSA":
757160814Ssimon			(pkey_type == TYPE_DSA)?"DSA":"EC");
75855714Skris
75955714Skris		if ((pkey=EVP_PKEY_new()) == NULL) goto end;
76055714Skris
761109998Smarkm#ifndef OPENSSL_NO_RSA
762160814Ssimon		BN_GENCB_set(&cb, req_cb, bio_err);
76355714Skris		if (pkey_type == TYPE_RSA)
76455714Skris			{
765160814Ssimon			RSA *rsa = RSA_new();
766160814Ssimon			BIGNUM *bn = BN_new();
767160814Ssimon			if(!bn || !rsa || !BN_set_word(bn, 0x10001) ||
768160814Ssimon					!RSA_generate_key_ex(rsa, newkey, bn, &cb) ||
769160814Ssimon					!EVP_PKEY_assign_RSA(pkey, rsa))
770160814Ssimon				{
771160814Ssimon				if(bn) BN_free(bn);
772160814Ssimon				if(rsa) RSA_free(rsa);
77355714Skris				goto end;
774160814Ssimon				}
775160814Ssimon			BN_free(bn);
77655714Skris			}
77755714Skris		else
77855714Skris#endif
779109998Smarkm#ifndef OPENSSL_NO_DSA
78055714Skris			if (pkey_type == TYPE_DSA)
78155714Skris			{
78255714Skris			if (!DSA_generate_key(dsa_params)) goto end;
78355714Skris			if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
78455714Skris			dsa_params=NULL;
78555714Skris			}
78655714Skris#endif
787160814Ssimon#ifndef OPENSSL_NO_ECDSA
788160814Ssimon			if (pkey_type == TYPE_EC)
789160814Ssimon			{
790160814Ssimon			if (!EC_KEY_generate_key(ec_params)) goto end;
791160814Ssimon			if (!EVP_PKEY_assign_EC_KEY(pkey, ec_params))
792160814Ssimon				goto end;
793160814Ssimon			ec_params = NULL;
794160814Ssimon			}
795160814Ssimon#endif
79655714Skris
79759191Skris		app_RAND_write_file(randfile, bio_err);
79855714Skris
79955714Skris		if (pkey == NULL) goto end;
80055714Skris
80155714Skris		if (keyout == NULL)
802109998Smarkm			{
803109998Smarkm			keyout=NCONF_get_string(req_conf,SECTION,KEYFILE);
804109998Smarkm			if (keyout == NULL)
805109998Smarkm				ERR_clear_error();
806109998Smarkm			}
807109998Smarkm
80855714Skris		if (keyout == NULL)
80955714Skris			{
81055714Skris			BIO_printf(bio_err,"writing new private key to stdout\n");
81155714Skris			BIO_set_fp(out,stdout,BIO_NOCLOSE);
812109998Smarkm#ifdef OPENSSL_SYS_VMS
81368651Skris			{
81468651Skris			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
81568651Skris			out = BIO_push(tmpbio, out);
81655714Skris			}
81768651Skris#endif
81868651Skris			}
81955714Skris		else
82055714Skris			{
82155714Skris			BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
82255714Skris			if (BIO_write_filename(out,keyout) <= 0)
82355714Skris				{
82455714Skris				perror(keyout);
82555714Skris				goto end;
82655714Skris				}
82755714Skris			}
82855714Skris
829109998Smarkm		p=NCONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
83055714Skris		if (p == NULL)
831109998Smarkm			{
832109998Smarkm			ERR_clear_error();
833109998Smarkm			p=NCONF_get_string(req_conf,SECTION,"encrypt_key");
834109998Smarkm			if (p == NULL)
835109998Smarkm				ERR_clear_error();
836109998Smarkm			}
83755714Skris		if ((p != NULL) && (strcmp(p,"no") == 0))
83855714Skris			cipher=NULL;
83955714Skris		if (nodes) cipher=NULL;
84055714Skris
84155714Skris		i=0;
84255714Skrisloop:
84355714Skris		if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
84459191Skris			NULL,0,NULL,passout))
84555714Skris			{
84655714Skris			if ((ERR_GET_REASON(ERR_peek_error()) ==
84755714Skris				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
84855714Skris				{
84955714Skris				ERR_clear_error();
85055714Skris				i++;
85155714Skris				goto loop;
85255714Skris				}
85355714Skris			goto end;
85455714Skris			}
85555714Skris		BIO_printf(bio_err,"-----\n");
85655714Skris		}
85755714Skris
85855714Skris	if (!newreq)
85955714Skris		{
86055714Skris		/* Since we are using a pre-existing certificate
86155714Skris		 * request, the kludge 'format' info should not be
86255714Skris		 * changed. */
86355714Skris		kludge= -1;
86455714Skris		if (infile == NULL)
86555714Skris			BIO_set_fp(in,stdin,BIO_NOCLOSE);
86655714Skris		else
86755714Skris			{
86855714Skris			if (BIO_read_filename(in,infile) <= 0)
86955714Skris				{
87055714Skris				perror(infile);
87155714Skris				goto end;
87255714Skris				}
87355714Skris			}
87455714Skris
87555714Skris		if	(informat == FORMAT_ASN1)
87655714Skris			req=d2i_X509_REQ_bio(in,NULL);
87755714Skris		else if (informat == FORMAT_PEM)
87855714Skris			req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
87955714Skris		else
88055714Skris			{
88155714Skris			BIO_printf(bio_err,"bad input format specified for X509 request\n");
88255714Skris			goto end;
88355714Skris			}
88455714Skris		if (req == NULL)
88555714Skris			{
88655714Skris			BIO_printf(bio_err,"unable to load X509 request\n");
88755714Skris			goto end;
88855714Skris			}
88955714Skris		}
89055714Skris
89155714Skris	if (newreq || x509)
89255714Skris		{
89355714Skris		if (pkey == NULL)
89455714Skris			{
89555714Skris			BIO_printf(bio_err,"you need to specify a private key\n");
89655714Skris			goto end;
89755714Skris			}
898109998Smarkm#ifndef OPENSSL_NO_DSA
89972613Skris		if (pkey->type == EVP_PKEY_DSA)
90072613Skris			digest=EVP_dss1();
90172613Skris#endif
902160814Ssimon#ifndef OPENSSL_NO_ECDSA
903160814Ssimon		if (pkey->type == EVP_PKEY_EC)
904160814Ssimon			digest=EVP_ecdsa();
905160814Ssimon#endif
90655714Skris		if (req == NULL)
90755714Skris			{
90855714Skris			req=X509_REQ_new();
90955714Skris			if (req == NULL)
91055714Skris				{
91155714Skris				goto end;
91255714Skris				}
91355714Skris
914160814Ssimon			i=make_REQ(req,pkey,subj,multirdn,!x509, chtype);
915109998Smarkm			subj=NULL; /* done processing '-subj' option */
916109998Smarkm			if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
917109998Smarkm				{
918109998Smarkm				sk_X509_ATTRIBUTE_free(req->req_info->attributes);
919109998Smarkm				req->req_info->attributes = NULL;
920109998Smarkm				}
92155714Skris			if (!i)
92255714Skris				{
92355714Skris				BIO_printf(bio_err,"problems making Certificate Request\n");
92455714Skris				goto end;
92555714Skris				}
92655714Skris			}
92755714Skris		if (x509)
92855714Skris			{
92955714Skris			EVP_PKEY *tmppkey;
93055714Skris			X509V3_CTX ext_ctx;
93155714Skris			if ((x509ss=X509_new()) == NULL) goto end;
93255714Skris
93355714Skris			/* Set version to V3 */
934127128Snectar			if(extensions && !X509_set_version(x509ss, 2)) goto end;
935109998Smarkm			if (serial)
936109998Smarkm				{
937109998Smarkm				if (!X509_set_serialNumber(x509ss, serial)) goto end;
938109998Smarkm				}
939109998Smarkm			else
940109998Smarkm				{
941142425Snectar				if (!rand_serial(NULL,
942142425Snectar					X509_get_serialNumber(x509ss)))
943142425Snectar						goto end;
944109998Smarkm				}
94555714Skris
946100928Snectar			if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end;
947100928Snectar			if (!X509_gmtime_adj(X509_get_notBefore(x509ss),0)) goto end;
948100928Snectar			if (!X509_gmtime_adj(X509_get_notAfter(x509ss), (long)60*60*24*days)) goto end;
949100928Snectar			if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) goto end;
95055714Skris			tmppkey = X509_REQ_get_pubkey(req);
951100928Snectar			if (!tmppkey || !X509_set_pubkey(x509ss,tmppkey)) goto end;
95255714Skris			EVP_PKEY_free(tmppkey);
95355714Skris
95455714Skris			/* Set up V3 context struct */
95555714Skris
95655714Skris			X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
957109998Smarkm			X509V3_set_nconf(&ext_ctx, req_conf);
95855714Skris
95955714Skris			/* Add extensions */
960109998Smarkm			if(extensions && !X509V3_EXT_add_nconf(req_conf,
96155714Skris				 	&ext_ctx, extensions, x509ss))
962109998Smarkm				{
963109998Smarkm				BIO_printf(bio_err,
964109998Smarkm					"Error Loading extension section %s\n",
965109998Smarkm					extensions);
966109998Smarkm				goto end;
967109998Smarkm				}
968109998Smarkm
96955714Skris			if (!(i=X509_sign(x509ss,pkey,digest)))
97055714Skris				goto end;
97155714Skris			}
97255714Skris		else
97355714Skris			{
97459191Skris			X509V3_CTX ext_ctx;
97559191Skris
97659191Skris			/* Set up V3 context struct */
97759191Skris
97859191Skris			X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
979109998Smarkm			X509V3_set_nconf(&ext_ctx, req_conf);
98059191Skris
98159191Skris			/* Add extensions */
982109998Smarkm			if(req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
98359191Skris				 	&ext_ctx, req_exts, req))
984109998Smarkm				{
985109998Smarkm				BIO_printf(bio_err,
986109998Smarkm					"Error Loading extension section %s\n",
987109998Smarkm					req_exts);
988109998Smarkm				goto end;
989109998Smarkm				}
99055714Skris			if (!(i=X509_REQ_sign(req,pkey,digest)))
99155714Skris				goto end;
99255714Skris			}
99355714Skris		}
99455714Skris
995109998Smarkm	if (subj && x509)
996109998Smarkm		{
997109998Smarkm		BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
998109998Smarkm		goto end;
999109998Smarkm		}
1000109998Smarkm
1001109998Smarkm	if (subj && !x509)
1002109998Smarkm		{
1003109998Smarkm		if (verbose)
1004109998Smarkm			{
1005109998Smarkm			BIO_printf(bio_err, "Modifying Request's Subject\n");
1006109998Smarkm			print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
1007109998Smarkm			}
1008109998Smarkm
1009160814Ssimon		if (build_subject(req, subj, chtype, multirdn) == 0)
1010109998Smarkm			{
1011109998Smarkm			BIO_printf(bio_err, "ERROR: cannot modify subject\n");
1012109998Smarkm			ex=1;
1013109998Smarkm			goto end;
1014109998Smarkm			}
1015109998Smarkm
1016109998Smarkm		req->req_info->enc.modified = 1;
1017109998Smarkm
1018109998Smarkm		if (verbose)
1019109998Smarkm			{
1020109998Smarkm			print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
1021109998Smarkm			}
1022109998Smarkm		}
1023109998Smarkm
102455714Skris	if (verify && !x509)
102555714Skris		{
102655714Skris		int tmp=0;
102755714Skris
102855714Skris		if (pkey == NULL)
102955714Skris			{
103055714Skris			pkey=X509_REQ_get_pubkey(req);
103155714Skris			tmp=1;
103255714Skris			if (pkey == NULL) goto end;
103355714Skris			}
103455714Skris
103555714Skris		i=X509_REQ_verify(req,pkey);
103655714Skris		if (tmp) {
103755714Skris			EVP_PKEY_free(pkey);
103855714Skris			pkey=NULL;
103955714Skris		}
104055714Skris
104155714Skris		if (i < 0)
104255714Skris			{
104355714Skris			goto end;
104455714Skris			}
104555714Skris		else if (i == 0)
104655714Skris			{
104755714Skris			BIO_printf(bio_err,"verify failure\n");
1048109998Smarkm			ERR_print_errors(bio_err);
104955714Skris			}
105055714Skris		else /* if (i > 0) */
105155714Skris			BIO_printf(bio_err,"verify OK\n");
105255714Skris		}
105355714Skris
1054109998Smarkm	if (noout && !text && !modulus && !subject && !pubkey)
105555714Skris		{
105655714Skris		ex=0;
105755714Skris		goto end;
105855714Skris		}
105955714Skris
106055714Skris	if (outfile == NULL)
106168651Skris		{
106255714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE);
1063109998Smarkm#ifdef OPENSSL_SYS_VMS
106468651Skris		{
106568651Skris		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
106668651Skris		out = BIO_push(tmpbio, out);
106768651Skris		}
106868651Skris#endif
106968651Skris		}
107055714Skris	else
107155714Skris		{
107255714Skris		if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
107355714Skris			i=(int)BIO_append_filename(out,outfile);
107455714Skris		else
107555714Skris			i=(int)BIO_write_filename(out,outfile);
107655714Skris		if (!i)
107755714Skris			{
107855714Skris			perror(outfile);
107955714Skris			goto end;
108055714Skris			}
108155714Skris		}
108255714Skris
1083109998Smarkm	if (pubkey)
1084109998Smarkm		{
1085109998Smarkm		EVP_PKEY *tpubkey;
1086109998Smarkm		tpubkey=X509_REQ_get_pubkey(req);
1087109998Smarkm		if (tpubkey == NULL)
1088109998Smarkm			{
1089109998Smarkm			BIO_printf(bio_err,"Error getting public key\n");
1090109998Smarkm			ERR_print_errors(bio_err);
1091109998Smarkm			goto end;
1092109998Smarkm			}
1093109998Smarkm		PEM_write_bio_PUBKEY(out, tpubkey);
1094109998Smarkm		EVP_PKEY_free(tpubkey);
1095109998Smarkm		}
1096109998Smarkm
109755714Skris	if (text)
109855714Skris		{
109955714Skris		if (x509)
1100109998Smarkm			X509_print_ex(out, x509ss, nmflag, reqflag);
110155714Skris		else
1102109998Smarkm			X509_REQ_print_ex(out, req, nmflag, reqflag);
110355714Skris		}
110455714Skris
1105109998Smarkm	if(subject)
1106109998Smarkm		{
1107109998Smarkm		if(x509)
1108109998Smarkm			print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag);
1109109998Smarkm		else
1110109998Smarkm			print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag);
1111109998Smarkm		}
1112109998Smarkm
111355714Skris	if (modulus)
111455714Skris		{
1115109998Smarkm		EVP_PKEY *tpubkey;
111655714Skris
111755714Skris		if (x509)
1118109998Smarkm			tpubkey=X509_get_pubkey(x509ss);
111955714Skris		else
1120109998Smarkm			tpubkey=X509_REQ_get_pubkey(req);
1121109998Smarkm		if (tpubkey == NULL)
112255714Skris			{
112355714Skris			fprintf(stdout,"Modulus=unavailable\n");
112455714Skris			goto end;
112555714Skris			}
112655714Skris		fprintf(stdout,"Modulus=");
1127109998Smarkm#ifndef OPENSSL_NO_RSA
1128109998Smarkm		if (tpubkey->type == EVP_PKEY_RSA)
1129109998Smarkm			BN_print(out,tpubkey->pkey.rsa->n);
113055714Skris		else
113155714Skris#endif
113255714Skris			fprintf(stdout,"Wrong Algorithm type");
1133109998Smarkm		EVP_PKEY_free(tpubkey);
113455714Skris		fprintf(stdout,"\n");
113555714Skris		}
113655714Skris
113755714Skris	if (!noout && !x509)
113855714Skris		{
113955714Skris		if 	(outformat == FORMAT_ASN1)
114055714Skris			i=i2d_X509_REQ_bio(out,req);
114159191Skris		else if (outformat == FORMAT_PEM) {
114259191Skris			if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req);
114359191Skris			else i=PEM_write_bio_X509_REQ(out,req);
114459191Skris		} else {
114555714Skris			BIO_printf(bio_err,"bad output format specified for outfile\n");
114655714Skris			goto end;
114755714Skris			}
114855714Skris		if (!i)
114955714Skris			{
115055714Skris			BIO_printf(bio_err,"unable to write X509 request\n");
115155714Skris			goto end;
115255714Skris			}
115355714Skris		}
115455714Skris	if (!noout && x509 && (x509ss != NULL))
115555714Skris		{
115655714Skris		if 	(outformat == FORMAT_ASN1)
115755714Skris			i=i2d_X509_bio(out,x509ss);
115855714Skris		else if (outformat == FORMAT_PEM)
115955714Skris			i=PEM_write_bio_X509(out,x509ss);
116055714Skris		else	{
116155714Skris			BIO_printf(bio_err,"bad output format specified for outfile\n");
116255714Skris			goto end;
116355714Skris			}
116455714Skris		if (!i)
116555714Skris			{
116655714Skris			BIO_printf(bio_err,"unable to write X509 certificate\n");
116755714Skris			goto end;
116855714Skris			}
116955714Skris		}
117055714Skris	ex=0;
117155714Skrisend:
1172109998Smarkm#ifndef MONOLITH
1173109998Smarkm	if(to_free)
1174109998Smarkm		OPENSSL_free(to_free);
1175109998Smarkm#endif
117655714Skris	if (ex)
117755714Skris		{
117855714Skris		ERR_print_errors(bio_err);
117955714Skris		}
1180109998Smarkm	if ((req_conf != NULL) && (req_conf != config)) NCONF_free(req_conf);
118155714Skris	BIO_free(in);
118268651Skris	BIO_free_all(out);
118355714Skris	EVP_PKEY_free(pkey);
118455714Skris	X509_REQ_free(req);
118555714Skris	X509_free(x509ss);
1186109998Smarkm	ASN1_INTEGER_free(serial);
118768651Skris	if(passargin && passin) OPENSSL_free(passin);
118868651Skris	if(passargout && passout) OPENSSL_free(passout);
118955714Skris	OBJ_cleanup();
1190109998Smarkm#ifndef OPENSSL_NO_DSA
119155714Skris	if (dsa_params != NULL) DSA_free(dsa_params);
119255714Skris#endif
1193160814Ssimon#ifndef OPENSSL_NO_ECDSA
1194160814Ssimon	if (ec_params != NULL) EC_KEY_free(ec_params);
1195160814Ssimon#endif
1196109998Smarkm	apps_shutdown();
1197109998Smarkm	OPENSSL_EXIT(ex);
119855714Skris	}
119955714Skris
1200160814Ssimonstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
1201160814Ssimon			int attribs, unsigned long chtype)
120255714Skris	{
120355714Skris	int ret=0,i;
120459191Skris	char no_prompt = 0;
120559191Skris	STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
120659191Skris	char *tmp, *dn_sect,*attr_sect;
120759191Skris
1208109998Smarkm	tmp=NCONF_get_string(req_conf,SECTION,PROMPT);
1209109998Smarkm	if (tmp == NULL)
1210109998Smarkm		ERR_clear_error();
121159191Skris	if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1;
121259191Skris
1213109998Smarkm	dn_sect=NCONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
121459191Skris	if (dn_sect == NULL)
121555714Skris		{
121655714Skris		BIO_printf(bio_err,"unable to find '%s' in config\n",
121755714Skris			DISTINGUISHED_NAME);
121855714Skris		goto err;
121955714Skris		}
1220109998Smarkm	dn_sk=NCONF_get_section(req_conf,dn_sect);
122159191Skris	if (dn_sk == NULL)
122255714Skris		{
122359191Skris		BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect);
122455714Skris		goto err;
122555714Skris		}
122655714Skris
1227109998Smarkm	attr_sect=NCONF_get_string(req_conf,SECTION,ATTRIBUTES);
122859191Skris	if (attr_sect == NULL)
1229109998Smarkm		{
1230109998Smarkm		ERR_clear_error();
123159191Skris		attr_sk=NULL;
1232109998Smarkm		}
123355714Skris	else
123455714Skris		{
1235109998Smarkm		attr_sk=NCONF_get_section(req_conf,attr_sect);
123659191Skris		if (attr_sk == NULL)
123755714Skris			{
123859191Skris			BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect);
123955714Skris			goto err;
124055714Skris			}
124155714Skris		}
124255714Skris
124359191Skris	/* setup version number */
124459191Skris	if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
124555714Skris
1246109998Smarkm	if (no_prompt)
1247109998Smarkm		i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1248109998Smarkm	else
1249109998Smarkm		{
1250109998Smarkm		if (subj)
1251160814Ssimon			i = build_subject(req, subj, chtype, multirdn);
1252109998Smarkm		else
1253109998Smarkm			i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
1254109998Smarkm		}
125559191Skris	if(!i) goto err;
125659191Skris
1257100928Snectar	if (!X509_REQ_set_pubkey(req,pkey)) goto err;
125859191Skris
125959191Skris	ret=1;
126059191Skriserr:
126159191Skris	return(ret);
126259191Skris	}
126359191Skris
1264109998Smarkm/*
1265109998Smarkm * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1266109998Smarkm * where characters may be escaped by \
1267109998Smarkm */
1268160814Ssimonstatic int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn)
1269109998Smarkm	{
1270109998Smarkm	X509_NAME *n;
127159191Skris
1272160814Ssimon	if (!(n = parse_name(subject, chtype, multirdn)))
1273109998Smarkm		return 0;
1274109998Smarkm
1275109998Smarkm	if (!X509_REQ_set_subject_name(req, n))
1276109998Smarkm		{
1277109998Smarkm		X509_NAME_free(n);
1278109998Smarkm		return 0;
1279109998Smarkm		}
1280109998Smarkm	X509_NAME_free(n);
1281109998Smarkm	return 1;
1282109998Smarkm}
1283109998Smarkm
1284109998Smarkm
128559191Skrisstatic int prompt_info(X509_REQ *req,
128659191Skris		STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1287109998Smarkm		STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
1288109998Smarkm		unsigned long chtype)
128959191Skris	{
129059191Skris	int i;
129159191Skris	char *p,*q;
129259191Skris	char buf[100];
1293160814Ssimon	int nid, mval;
1294109998Smarkm	long n_min,n_max;
1295160814Ssimon	char *type, *value;
1296160814Ssimon	const char *def;
129759191Skris	CONF_VALUE *v;
129859191Skris	X509_NAME *subj;
129959191Skris	subj = X509_REQ_get_subject_name(req);
130055714Skris
1301109998Smarkm	if(!batch)
1302109998Smarkm		{
1303109998Smarkm		BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
1304109998Smarkm		BIO_printf(bio_err,"into your certificate request.\n");
1305109998Smarkm		BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
1306109998Smarkm		BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
1307109998Smarkm		BIO_printf(bio_err,"For some fields there will be a default value,\n");
1308109998Smarkm		BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
1309109998Smarkm		BIO_printf(bio_err,"-----\n");
1310109998Smarkm		}
131155714Skris
1312109998Smarkm
131359191Skris	if (sk_CONF_VALUE_num(dn_sk))
131455714Skris		{
131555714Skris		i= -1;
131655714Skrisstart:		for (;;)
131755714Skris			{
131855714Skris			i++;
131959191Skris			if (sk_CONF_VALUE_num(dn_sk) <= i) break;
132055714Skris
132159191Skris			v=sk_CONF_VALUE_value(dn_sk,i);
132255714Skris			p=q=NULL;
132355714Skris			type=v->name;
132455714Skris			if(!check_end(type,"_min") || !check_end(type,"_max") ||
132555714Skris				!check_end(type,"_default") ||
132655714Skris					 !check_end(type,"_value")) continue;
132755714Skris			/* Skip past any leading X. X: X, etc to allow for
132855714Skris			 * multiple instances
132955714Skris			 */
133055714Skris			for(p = v->name; *p ; p++)
133155714Skris				if ((*p == ':') || (*p == ',') ||
133255714Skris							 (*p == '.')) {
133355714Skris					p++;
133455714Skris					if(*p) type = p;
133555714Skris					break;
133655714Skris				}
1337160814Ssimon			if (*type == '+')
1338160814Ssimon				{
1339160814Ssimon				mval = -1;
1340160814Ssimon				type++;
1341160814Ssimon				}
1342160814Ssimon			else
1343160814Ssimon				mval = 0;
134455714Skris			/* If OBJ not recognised ignore it */
134555714Skris			if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
1346127128Snectar			if (BIO_snprintf(buf,sizeof buf,"%s_default",v->name)
1347160814Ssimon				>= (int)sizeof(buf))
1348109998Smarkm			   {
1349109998Smarkm			   BIO_printf(bio_err,"Name '%s' too long\n",v->name);
1350109998Smarkm			   return 0;
1351109998Smarkm			   }
1352109998Smarkm
1353109998Smarkm			if ((def=NCONF_get_string(req_conf,dn_sect,buf)) == NULL)
1354109998Smarkm				{
1355109998Smarkm				ERR_clear_error();
135655714Skris				def="";
1357109998Smarkm				}
1358127128Snectar
1359127128Snectar			BIO_snprintf(buf,sizeof buf,"%s_value",v->name);
1360109998Smarkm			if ((value=NCONF_get_string(req_conf,dn_sect,buf)) == NULL)
1361109998Smarkm				{
1362109998Smarkm				ERR_clear_error();
136355714Skris				value=NULL;
1364109998Smarkm				}
136555714Skris
1366127128Snectar			BIO_snprintf(buf,sizeof buf,"%s_min",v->name);
1367109998Smarkm			if (!NCONF_get_number(req_conf,dn_sect,buf, &n_min))
1368111147Snectar				{
1369111147Snectar				ERR_clear_error();
1370109998Smarkm				n_min = -1;
1371111147Snectar				}
137255714Skris
1373127128Snectar			BIO_snprintf(buf,sizeof buf,"%s_max",v->name);
1374109998Smarkm			if (!NCONF_get_number(req_conf,dn_sect,buf, &n_max))
1375111147Snectar				{
1376111147Snectar				ERR_clear_error();
1377109998Smarkm				n_max = -1;
1378111147Snectar				}
137955714Skris
138059191Skris			if (!add_DN_object(subj,v->value,def,value,nid,
1381160814Ssimon				n_min,n_max, chtype, mval))
138259191Skris				return 0;
138355714Skris			}
138459191Skris		if (X509_NAME_entry_count(subj) == 0)
138555714Skris			{
138655714Skris			BIO_printf(bio_err,"error, no objects specified in config file\n");
138759191Skris			return 0;
138855714Skris			}
138955714Skris
139055714Skris		if (attribs)
139155714Skris			{
1392109998Smarkm			if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
139355714Skris				{
139455714Skris				BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
139555714Skris				BIO_printf(bio_err,"to be sent with your certificate request\n");
139655714Skris				}
139755714Skris
139855714Skris			i= -1;
139955714Skrisstart2:			for (;;)
140055714Skris				{
140155714Skris				i++;
140259191Skris				if ((attr_sk == NULL) ||
140359191Skris					    (sk_CONF_VALUE_num(attr_sk) <= i))
140455714Skris					break;
140555714Skris
140659191Skris				v=sk_CONF_VALUE_value(attr_sk,i);
140755714Skris				type=v->name;
140855714Skris				if ((nid=OBJ_txt2nid(type)) == NID_undef)
140955714Skris					goto start2;
141055714Skris
1411127128Snectar				if (BIO_snprintf(buf,sizeof buf,"%s_default",type)
1412160814Ssimon					>= (int)sizeof(buf))
1413109998Smarkm				   {
1414109998Smarkm				   BIO_printf(bio_err,"Name '%s' too long\n",v->name);
1415109998Smarkm				   return 0;
1416109998Smarkm				   }
1417109998Smarkm
1418109998Smarkm				if ((def=NCONF_get_string(req_conf,attr_sect,buf))
141955714Skris					== NULL)
1420109998Smarkm					{
1421109998Smarkm					ERR_clear_error();
142255714Skris					def="";
1423109998Smarkm					}
142455714Skris
1425109998Smarkm
1426127128Snectar				BIO_snprintf(buf,sizeof buf,"%s_value",type);
1427109998Smarkm				if ((value=NCONF_get_string(req_conf,attr_sect,buf))
142855714Skris					== NULL)
1429109998Smarkm					{
1430109998Smarkm					ERR_clear_error();
143155714Skris					value=NULL;
1432109998Smarkm					}
143355714Skris
1434127128Snectar				BIO_snprintf(buf,sizeof buf,"%s_min",type);
1435109998Smarkm				if (!NCONF_get_number(req_conf,attr_sect,buf, &n_min))
1436206046Ssimon					{
1437206046Ssimon					ERR_clear_error();
1438109998Smarkm					n_min = -1;
1439206046Ssimon					}
144055714Skris
1441127128Snectar				BIO_snprintf(buf,sizeof buf,"%s_max",type);
1442109998Smarkm				if (!NCONF_get_number(req_conf,attr_sect,buf, &n_max))
1443206046Ssimon					{
1444206046Ssimon					ERR_clear_error();
1445109998Smarkm					n_max = -1;
1446206046Ssimon					}
144755714Skris
144859191Skris				if (!add_attribute_object(req,
1449109998Smarkm					v->value,def,value,nid,n_min,n_max, chtype))
145059191Skris					return 0;
145155714Skris				}
145255714Skris			}
145355714Skris		}
145455714Skris	else
145555714Skris		{
145655714Skris		BIO_printf(bio_err,"No template, please set one up.\n");
145759191Skris		return 0;
145855714Skris		}
145955714Skris
146059191Skris	return 1;
146155714Skris
146255714Skris	}
146355714Skris
146459191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1465109998Smarkm			STACK_OF(CONF_VALUE) *attr_sk, int attribs, unsigned long chtype)
146659191Skris	{
146759191Skris	int i;
146859191Skris	char *p,*q;
146959191Skris	char *type;
147059191Skris	CONF_VALUE *v;
147159191Skris	X509_NAME *subj;
147259191Skris
147359191Skris	subj = X509_REQ_get_subject_name(req);
147459191Skris
147559191Skris	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
147659191Skris		{
1477160814Ssimon		int mval;
147859191Skris		v=sk_CONF_VALUE_value(dn_sk,i);
147959191Skris		p=q=NULL;
148059191Skris		type=v->name;
148159191Skris		/* Skip past any leading X. X: X, etc to allow for
148259191Skris		 * multiple instances
148359191Skris		 */
148459191Skris		for(p = v->name; *p ; p++)
148568651Skris#ifndef CHARSET_EBCDIC
148659191Skris			if ((*p == ':') || (*p == ',') || (*p == '.')) {
148768651Skris#else
148868651Skris			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) {
148968651Skris#endif
149059191Skris				p++;
149159191Skris				if(*p) type = p;
149259191Skris				break;
149359191Skris			}
1494160814Ssimon#ifndef CHARSET_EBCDIC
1495160814Ssimon		if (*p == '+')
1496160814Ssimon#else
1497160814Ssimon		if (*p == os_toascii['+'])
1498160814Ssimon#endif
1499160814Ssimon			{
1500160814Ssimon			p++;
1501160814Ssimon			mval = -1;
1502160814Ssimon			}
1503160814Ssimon		else
1504160814Ssimon			mval = 0;
1505109998Smarkm		if (!X509_NAME_add_entry_by_txt(subj,type, chtype,
1506160814Ssimon				(unsigned char *) v->value,-1,-1,mval)) return 0;
150759191Skris
150859191Skris		}
150959191Skris
151059191Skris		if (!X509_NAME_entry_count(subj))
151159191Skris			{
151259191Skris			BIO_printf(bio_err,"error, no objects specified in config file\n");
151359191Skris			return 0;
151459191Skris			}
151559191Skris		if (attribs)
151659191Skris			{
151759191Skris			for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++)
151859191Skris				{
151959191Skris				v=sk_CONF_VALUE_value(attr_sk,i);
1520109998Smarkm				if(!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
152159191Skris					(unsigned char *)v->value, -1)) return 0;
152259191Skris				}
152359191Skris			}
152459191Skris	return 1;
152559191Skris	}
152659191Skris
152759191Skris
1528160814Ssimonstatic int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
1529160814Ssimon	     int nid, int n_min, int n_max, unsigned long chtype, int mval)
153055714Skris	{
153159191Skris	int i,ret=0;
153255714Skris	MS_STATIC char buf[1024];
153359191Skrisstart:
1534109998Smarkm	if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
153555714Skris	(void)BIO_flush(bio_err);
1536109998Smarkm	if(value != NULL)
153755714Skris		{
1538127128Snectar		BUF_strlcpy(buf,value,sizeof buf);
1539127128Snectar		BUF_strlcat(buf,"\n",sizeof buf);
154055714Skris		BIO_printf(bio_err,"%s\n",value);
154155714Skris		}
154255714Skris	else
154355714Skris		{
154455714Skris		buf[0]='\0';
1545109998Smarkm		if (!batch)
1546109998Smarkm			{
1547205128Ssimon			if (!fgets(buf,sizeof buf,stdin))
1548205128Ssimon				return 0;
1549109998Smarkm			}
1550109998Smarkm		else
1551109998Smarkm			{
1552109998Smarkm			buf[0] = '\n';
1553109998Smarkm			buf[1] = '\0';
1554109998Smarkm			}
155555714Skris		}
155655714Skris
155755714Skris	if (buf[0] == '\0') return(0);
155855714Skris	else if (buf[0] == '\n')
155955714Skris		{
156055714Skris		if ((def == NULL) || (def[0] == '\0'))
156155714Skris			return(1);
1562127128Snectar		BUF_strlcpy(buf,def,sizeof buf);
1563127128Snectar		BUF_strlcat(buf,"\n",sizeof buf);
156455714Skris		}
156555714Skris	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
156655714Skris
156755714Skris	i=strlen(buf);
156855714Skris	if (buf[i-1] != '\n')
156955714Skris		{
157055714Skris		BIO_printf(bio_err,"weird input :-(\n");
157155714Skris		return(0);
157255714Skris		}
157355714Skris	buf[--i]='\0';
157455714Skris#ifdef CHARSET_EBCDIC
157555714Skris	ebcdic2ascii(buf, buf, i);
157655714Skris#endif
1577267285Sjkim	if(!req_check_len(i, n_min, n_max))
1578267285Sjkim		{
1579267285Sjkim		if (batch || value)
1580267285Sjkim			return 0;
1581267285Sjkim		goto start;
1582267285Sjkim		}
1583267285Sjkim
1584109998Smarkm	if (!X509_NAME_add_entry_by_NID(n,nid, chtype,
1585160814Ssimon				(unsigned char *) buf, -1,-1,mval)) goto err;
158655714Skris	ret=1;
158755714Skriserr:
158855714Skris	return(ret);
158955714Skris	}
159055714Skris
1591160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
1592160814Ssimon				char *value, int nid, int n_min,
1593109998Smarkm				int n_max, unsigned long chtype)
159455714Skris	{
159559191Skris	int i;
159655714Skris	static char buf[1024];
159755714Skris
159855714Skrisstart:
1599109998Smarkm	if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
160055714Skris	(void)BIO_flush(bio_err);
160155714Skris	if (value != NULL)
160255714Skris		{
1603127128Snectar		BUF_strlcpy(buf,value,sizeof buf);
1604127128Snectar		BUF_strlcat(buf,"\n",sizeof buf);
160555714Skris		BIO_printf(bio_err,"%s\n",value);
160655714Skris		}
160755714Skris	else
160855714Skris		{
160955714Skris		buf[0]='\0';
1610109998Smarkm		if (!batch)
1611109998Smarkm			{
1612205128Ssimon			if (!fgets(buf,sizeof buf,stdin))
1613205128Ssimon				return 0;
1614109998Smarkm			}
1615109998Smarkm		else
1616109998Smarkm			{
1617109998Smarkm			buf[0] = '\n';
1618109998Smarkm			buf[1] = '\0';
1619109998Smarkm			}
162055714Skris		}
162155714Skris
162255714Skris	if (buf[0] == '\0') return(0);
162355714Skris	else if (buf[0] == '\n')
162455714Skris		{
162555714Skris		if ((def == NULL) || (def[0] == '\0'))
162655714Skris			return(1);
1627127128Snectar		BUF_strlcpy(buf,def,sizeof buf);
1628127128Snectar		BUF_strlcat(buf,"\n",sizeof buf);
162955714Skris		}
163055714Skris	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
163155714Skris
163255714Skris	i=strlen(buf);
163355714Skris	if (buf[i-1] != '\n')
163455714Skris		{
163555714Skris		BIO_printf(bio_err,"weird input :-(\n");
163655714Skris		return(0);
163755714Skris		}
163855714Skris	buf[--i]='\0';
163968651Skris#ifdef CHARSET_EBCDIC
164068651Skris	ebcdic2ascii(buf, buf, i);
164168651Skris#endif
1642267285Sjkim	if(!req_check_len(i, n_min, n_max))
1643267285Sjkim		{
1644267285Sjkim		if (batch || value)
1645267285Sjkim			return 0;
1646267285Sjkim		goto start;
1647267285Sjkim		}
164855714Skris
1649109998Smarkm	if(!X509_REQ_add1_attr_by_NID(req, nid, chtype,
165059191Skris					(unsigned char *)buf, -1)) {
165159191Skris		BIO_printf(bio_err, "Error adding attribute\n");
165259191Skris		ERR_print_errors(bio_err);
165355714Skris		goto err;
165459191Skris	}
165555714Skris
165655714Skris	return(1);
165755714Skriserr:
165855714Skris	return(0);
165955714Skris	}
166055714Skris
1661109998Smarkm#ifndef OPENSSL_NO_RSA
1662160814Ssimonstatic int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb)
166355714Skris	{
166455714Skris	char c='*';
166555714Skris
166655714Skris	if (p == 0) c='.';
166755714Skris	if (p == 1) c='+';
166855714Skris	if (p == 2) c='*';
166955714Skris	if (p == 3) c='\n';
1670160814Ssimon	BIO_write(cb->arg,&c,1);
1671160814Ssimon	(void)BIO_flush(cb->arg);
167255714Skris#ifdef LINT
167355714Skris	p=n;
167455714Skris#endif
1675160814Ssimon	return 1;
167655714Skris	}
167759191Skris#endif
167855714Skris
1679109998Smarkmstatic int req_check_len(int len, int n_min, int n_max)
168055714Skris	{
1681109998Smarkm	if ((n_min > 0) && (len < n_min))
168255714Skris		{
1683109998Smarkm		BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",n_min);
168455714Skris		return(0);
168555714Skris		}
1686109998Smarkm	if ((n_max >= 0) && (len > n_max))
168755714Skris		{
1688109998Smarkm		BIO_printf(bio_err,"string is too long, it needs to be less than  %d bytes long\n",n_max);
168955714Skris		return(0);
169055714Skris		}
169155714Skris	return(1);
169255714Skris	}
169355714Skris
169455714Skris/* Check if the end of a string matches 'end' */
1695160814Ssimonstatic int check_end(const char *str, const char *end)
169655714Skris{
169755714Skris	int elen, slen;
1698160814Ssimon	const char *tmp;
169955714Skris	elen = strlen(end);
170055714Skris	slen = strlen(str);
170155714Skris	if(elen > slen) return 1;
170255714Skris	tmp = str + slen - elen;
170355714Skris	return strcmp(tmp, end);
170455714Skris}
1705